mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-22 13:27:17 +01:00
Merge branch 'master' of github-meeh420:PrivacySolutions/i2pd
Note; we use _MSC_VER instead of _WIN32 for MSVC spesific code. * 'master' of github-meeh420:PrivacySolutions/i2pd: (35 commits) handle incoming datagramms send datagram through destination's thread incoming ipv6 connections support ipv6 for outgoing NTCP connections some cleanup Update Daemon.cpp Add Upstart job to debian packaging Implement reload in init script Rename init.d to i2pd.init Decouple logging and daemonization verify signature through remore identity moved remote RI and identity to TransportSession set unreachable trough NetDb moved AddressBook to ClientContext initialize router identity don't specify RI for inbound NTCP connections use remote router indentity take identity of local RI from private keys send datagram from SAM fixed windows build ... Conflicts: SAM.cpp
This commit is contained in:
commit
af0bdc2a5e
|
@ -11,14 +11,14 @@
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace data
|
namespace client
|
||||||
{
|
{
|
||||||
|
|
||||||
AddressBook::AddressBook (): m_IsLoaded (false), m_IsDowloading (false)
|
AddressBook::AddressBook (): m_IsLoaded (false), m_IsDowloading (false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AddressBook::GetIdentHash (const std::string& address, IdentHash& ident)
|
bool AddressBook::GetIdentHash (const std::string& address, i2p::data::IdentHash& ident)
|
||||||
{
|
{
|
||||||
auto pos = address.find(".b32.i2p");
|
auto pos = address.find(".b32.i2p");
|
||||||
if (pos != std::string::npos)
|
if (pos != std::string::npos)
|
||||||
|
@ -42,7 +42,7 @@ namespace data
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const IdentHash * AddressBook::FindAddress (const std::string& address)
|
const i2p::data::IdentHash * AddressBook::FindAddress (const std::string& address)
|
||||||
{
|
{
|
||||||
if (!m_IsLoaded)
|
if (!m_IsLoaded)
|
||||||
LoadHosts ();
|
LoadHosts ();
|
||||||
|
@ -57,7 +57,7 @@ namespace data
|
||||||
|
|
||||||
void AddressBook::InsertAddress (const std::string& address, const std::string& base64)
|
void AddressBook::InsertAddress (const std::string& address, const std::string& base64)
|
||||||
{
|
{
|
||||||
IdentityEx ident;
|
i2p::data::IdentityEx ident;
|
||||||
ident.FromBase64 (base64);
|
ident.FromBase64 (base64);
|
||||||
m_Addresses[address] = ident.GetIdentHash ();
|
m_Addresses[address] = ident.GetIdentHash ();
|
||||||
LogPrint (address,"->",ident.GetIdentHash ().ToBase32 (), ".b32.i2p added");
|
LogPrint (address,"->",ident.GetIdentHash ().ToBase32 (), ".b32.i2p added");
|
||||||
|
@ -118,7 +118,7 @@ namespace data
|
||||||
std::string name = s.substr(0, pos++);
|
std::string name = s.substr(0, pos++);
|
||||||
std::string addr = s.substr(pos);
|
std::string addr = s.substr(pos);
|
||||||
|
|
||||||
IdentityEx ident;
|
i2p::data::IdentityEx ident;
|
||||||
ident.FromBase64(addr);
|
ident.FromBase64(addr);
|
||||||
m_Addresses[name] = ident.GetIdentHash ();
|
m_Addresses[name] = ident.GetIdentHash ();
|
||||||
numAddresses++;
|
numAddresses++;
|
||||||
|
|
|
@ -11,15 +11,15 @@
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace data
|
namespace client
|
||||||
{
|
{
|
||||||
class AddressBook
|
class AddressBook
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
AddressBook ();
|
AddressBook ();
|
||||||
bool GetIdentHash (const std::string& address, IdentHash& ident);
|
bool GetIdentHash (const std::string& address, i2p::data::IdentHash& ident);
|
||||||
const IdentHash * FindAddress (const std::string& address);
|
const i2p::data::IdentHash * FindAddress (const std::string& address);
|
||||||
void InsertAddress (const std::string& address, const std::string& base64); // for jump service
|
void InsertAddress (const std::string& address, const std::string& base64); // for jump service
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -27,7 +27,7 @@ namespace data
|
||||||
void LoadHosts ();
|
void LoadHosts ();
|
||||||
void LoadHostsFromI2P ();
|
void LoadHostsFromI2P ();
|
||||||
|
|
||||||
std::map<std::string, IdentHash> m_Addresses;
|
std::map<std::string, i2p::data::IdentHash> m_Addresses;
|
||||||
bool m_IsLoaded, m_IsDowloading;
|
bool m_IsLoaded, m_IsDowloading;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ namespace client
|
||||||
{
|
{
|
||||||
if (!m_SharedLocalDestination)
|
if (!m_SharedLocalDestination)
|
||||||
{
|
{
|
||||||
m_SharedLocalDestination = new i2p::stream::StreamingDestination (false, i2p::data::SIGNING_KEY_TYPE_DSA_SHA1); // non-public, DSA
|
m_SharedLocalDestination = new ClientDestination (false, i2p::data::SIGNING_KEY_TYPE_DSA_SHA1); // non-public, DSA
|
||||||
m_Destinations[m_SharedLocalDestination->GetIdentity ().GetIdentHash ()] = m_SharedLocalDestination;
|
m_Destinations[m_SharedLocalDestination->GetIdentity ().GetIdentHash ()] = m_SharedLocalDestination;
|
||||||
m_SharedLocalDestination->Start ();
|
m_SharedLocalDestination->Start ();
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ namespace client
|
||||||
std::string ircDestination = i2p::util::config::GetArg("-ircdest", "");
|
std::string ircDestination = i2p::util::config::GetArg("-ircdest", "");
|
||||||
if (ircDestination.length () > 0) // ircdest is presented
|
if (ircDestination.length () > 0) // ircdest is presented
|
||||||
{
|
{
|
||||||
i2p::stream::StreamingDestination * localDestination = nullptr;
|
ClientDestination * localDestination = nullptr;
|
||||||
std::string ircKeys = i2p::util::config::GetArg("-irckeys", "");
|
std::string ircKeys = i2p::util::config::GetArg("-irckeys", "");
|
||||||
if (ircKeys.length () > 0)
|
if (ircKeys.length () > 0)
|
||||||
localDestination = i2p::client::context.LoadLocalDestination (ircKeys, false);
|
localDestination = i2p::client::context.LoadLocalDestination (ircKeys, false);
|
||||||
|
@ -125,7 +125,7 @@ namespace client
|
||||||
#else
|
#else
|
||||||
it->path();
|
it->path();
|
||||||
#endif
|
#endif
|
||||||
auto localDestination = new i2p::stream::StreamingDestination (fullPath, true);
|
auto localDestination = new ClientDestination (fullPath, true);
|
||||||
m_Destinations[localDestination->GetIdentHash ()] = localDestination;
|
m_Destinations[localDestination->GetIdentHash ()] = localDestination;
|
||||||
numDestinations++;
|
numDestinations++;
|
||||||
}
|
}
|
||||||
|
@ -134,25 +134,25 @@ namespace client
|
||||||
LogPrint (numDestinations, " local destinations loaded");
|
LogPrint (numDestinations, " local destinations loaded");
|
||||||
}
|
}
|
||||||
|
|
||||||
i2p::stream::StreamingDestination * ClientContext::LoadLocalDestination (const std::string& filename, bool isPublic)
|
ClientDestination * ClientContext::LoadLocalDestination (const std::string& filename, bool isPublic)
|
||||||
{
|
{
|
||||||
auto localDestination = new i2p::stream::StreamingDestination (i2p::util::filesystem::GetFullPath (filename), isPublic);
|
auto localDestination = new ClientDestination (i2p::util::filesystem::GetFullPath (filename), isPublic);
|
||||||
std::unique_lock<std::mutex> l(m_DestinationsMutex);
|
std::unique_lock<std::mutex> l(m_DestinationsMutex);
|
||||||
m_Destinations[localDestination->GetIdentHash ()] = localDestination;
|
m_Destinations[localDestination->GetIdentHash ()] = localDestination;
|
||||||
localDestination->Start ();
|
localDestination->Start ();
|
||||||
return localDestination;
|
return localDestination;
|
||||||
}
|
}
|
||||||
|
|
||||||
i2p::stream::StreamingDestination * ClientContext::CreateNewLocalDestination (bool isPublic, i2p::data::SigningKeyType sigType)
|
ClientDestination * ClientContext::CreateNewLocalDestination (bool isPublic, i2p::data::SigningKeyType sigType)
|
||||||
{
|
{
|
||||||
auto localDestination = new i2p::stream::StreamingDestination (isPublic, sigType);
|
auto localDestination = new ClientDestination (isPublic, sigType);
|
||||||
std::unique_lock<std::mutex> l(m_DestinationsMutex);
|
std::unique_lock<std::mutex> l(m_DestinationsMutex);
|
||||||
m_Destinations[localDestination->GetIdentHash ()] = localDestination;
|
m_Destinations[localDestination->GetIdentHash ()] = localDestination;
|
||||||
localDestination->Start ();
|
localDestination->Start ();
|
||||||
return localDestination;
|
return localDestination;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientContext::DeleteLocalDestination (i2p::stream::StreamingDestination * destination)
|
void ClientContext::DeleteLocalDestination (ClientDestination * destination)
|
||||||
{
|
{
|
||||||
if (!destination) return;
|
if (!destination) return;
|
||||||
auto it = m_Destinations.find (destination->GetIdentHash ());
|
auto it = m_Destinations.find (destination->GetIdentHash ());
|
||||||
|
@ -168,7 +168,7 @@ namespace client
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i2p::stream::StreamingDestination * ClientContext::CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic)
|
ClientDestination * ClientContext::CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic)
|
||||||
{
|
{
|
||||||
auto it = m_Destinations.find (keys.GetPublic ().GetIdentHash ());
|
auto it = m_Destinations.find (keys.GetPublic ().GetIdentHash ());
|
||||||
if (it != m_Destinations.end ())
|
if (it != m_Destinations.end ())
|
||||||
|
@ -181,14 +181,14 @@ namespace client
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto localDestination = new i2p::stream::StreamingDestination (keys, isPublic);
|
auto localDestination = new ClientDestination (keys, isPublic);
|
||||||
std::unique_lock<std::mutex> l(m_DestinationsMutex);
|
std::unique_lock<std::mutex> l(m_DestinationsMutex);
|
||||||
m_Destinations[keys.GetPublic ().GetIdentHash ()] = localDestination;
|
m_Destinations[keys.GetPublic ().GetIdentHash ()] = localDestination;
|
||||||
localDestination->Start ();
|
localDestination->Start ();
|
||||||
return localDestination;
|
return localDestination;
|
||||||
}
|
}
|
||||||
|
|
||||||
i2p::stream::StreamingDestination * ClientContext::FindLocalDestination (const i2p::data::IdentHash& destination) const
|
ClientDestination * ClientContext::FindLocalDestination (const i2p::data::IdentHash& destination) const
|
||||||
{
|
{
|
||||||
auto it = m_Destinations.find (destination);
|
auto it = m_Destinations.find (destination);
|
||||||
if (it != m_Destinations.end ())
|
if (it != m_Destinations.end ())
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "SOCKS.h"
|
#include "SOCKS.h"
|
||||||
#include "I2PTunnel.h"
|
#include "I2PTunnel.h"
|
||||||
#include "SAM.h"
|
#include "SAM.h"
|
||||||
|
#include "AddressBook.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
|
@ -22,12 +23,14 @@ namespace client
|
||||||
void Start ();
|
void Start ();
|
||||||
void Stop ();
|
void Stop ();
|
||||||
|
|
||||||
i2p::stream::StreamingDestination * GetSharedLocalDestination () const { return m_SharedLocalDestination; };
|
ClientDestination * GetSharedLocalDestination () const { return m_SharedLocalDestination; };
|
||||||
i2p::stream::StreamingDestination * CreateNewLocalDestination (bool isPublic = true, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1); // transient
|
ClientDestination * CreateNewLocalDestination (bool isPublic = true, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1); // transient
|
||||||
i2p::stream::StreamingDestination * CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true);
|
ClientDestination * CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true);
|
||||||
void DeleteLocalDestination (i2p::stream::StreamingDestination * destination);
|
void DeleteLocalDestination (ClientDestination * destination);
|
||||||
i2p::stream::StreamingDestination * FindLocalDestination (const i2p::data::IdentHash& destination) const;
|
ClientDestination * FindLocalDestination (const i2p::data::IdentHash& destination) const;
|
||||||
i2p::stream::StreamingDestination * LoadLocalDestination (const std::string& filename, bool isPublic);
|
ClientDestination * LoadLocalDestination (const std::string& filename, bool isPublic);
|
||||||
|
|
||||||
|
AddressBook& GetAddressBook () { return m_AddressBook; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -36,8 +39,10 @@ namespace client
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::mutex m_DestinationsMutex;
|
std::mutex m_DestinationsMutex;
|
||||||
std::map<i2p::data::IdentHash, i2p::stream::StreamingDestination *> m_Destinations;
|
std::map<i2p::data::IdentHash, ClientDestination *> m_Destinations;
|
||||||
i2p::stream::StreamingDestination * m_SharedLocalDestination;
|
ClientDestination * m_SharedLocalDestination;
|
||||||
|
|
||||||
|
AddressBook m_AddressBook;
|
||||||
|
|
||||||
i2p::proxy::HTTPProxy * m_HttpProxy;
|
i2p::proxy::HTTPProxy * m_HttpProxy;
|
||||||
i2p::proxy::SOCKSProxy * m_SocksProxy;
|
i2p::proxy::SOCKSProxy * m_SocksProxy;
|
||||||
|
|
|
@ -72,6 +72,8 @@ namespace i2p
|
||||||
if (i2p::util::config::GetArg("-unreachable", 0))
|
if (i2p::util::config::GetArg("-unreachable", 0))
|
||||||
i2p::context.SetUnreachable ();
|
i2p::context.SetUnreachable ();
|
||||||
|
|
||||||
|
i2p::context.SetSupportsV6 (i2p::util::config::GetArg("-v6", 0));
|
||||||
|
|
||||||
LogPrint("CMD parameters:");
|
LogPrint("CMD parameters:");
|
||||||
for (int i = 0; i < argc; ++i)
|
for (int i = 0; i < argc; ++i)
|
||||||
LogPrint(i, " ", argv[i]);
|
LogPrint(i, " ", argv[i]);
|
||||||
|
@ -103,7 +105,7 @@ namespace i2p
|
||||||
LogPrint("HTTP Server started");
|
LogPrint("HTTP Server started");
|
||||||
i2p::data::netdb.Start();
|
i2p::data::netdb.Start();
|
||||||
LogPrint("NetDB started");
|
LogPrint("NetDB started");
|
||||||
i2p::transports.Start();
|
i2p::transport::transports.Start();
|
||||||
LogPrint("Transports started");
|
LogPrint("Transports started");
|
||||||
i2p::tunnel::tunnels.Start();
|
i2p::tunnel::tunnels.Start();
|
||||||
LogPrint("Tunnels started");
|
LogPrint("Tunnels started");
|
||||||
|
@ -120,7 +122,7 @@ namespace i2p
|
||||||
LogPrint("Client stoped");
|
LogPrint("Client stoped");
|
||||||
i2p::tunnel::tunnels.Stop();
|
i2p::tunnel::tunnels.Stop();
|
||||||
LogPrint("Tunnels stoped");
|
LogPrint("Tunnels stoped");
|
||||||
i2p::transports.Stop();
|
i2p::transport::transports.Stop();
|
||||||
LogPrint("Transports stoped");
|
LogPrint("Transports stoped");
|
||||||
i2p::data::netdb.Stop();
|
i2p::data::netdb.Stop();
|
||||||
LogPrint("NetDB stoped");
|
LogPrint("NetDB stoped");
|
||||||
|
|
132
Datagram.cpp
Normal file
132
Datagram.cpp
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <cryptopp/sha.h>
|
||||||
|
#include <cryptopp/gzip.h>
|
||||||
|
#include "Log.h"
|
||||||
|
#include "TunnelBase.h"
|
||||||
|
#include "RouterContext.h"
|
||||||
|
#include "Destination.h"
|
||||||
|
#include "Datagram.h"
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace datagram
|
||||||
|
{
|
||||||
|
DatagramDestination::DatagramDestination (i2p::client::ClientDestination& owner):
|
||||||
|
m_Owner (owner)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatagramDestination::SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::LeaseSet& remote)
|
||||||
|
{
|
||||||
|
uint8_t buf[MAX_DATAGRAM_SIZE];
|
||||||
|
auto identityLen = m_Owner.GetIdentity ().ToBuffer (buf, MAX_DATAGRAM_SIZE);
|
||||||
|
uint8_t * signature = buf + identityLen;
|
||||||
|
auto signatureLen = m_Owner.GetIdentity ().GetSignatureLen ();
|
||||||
|
uint8_t * buf1 = signature + signatureLen;
|
||||||
|
size_t headerLen = identityLen + signatureLen;
|
||||||
|
|
||||||
|
memcpy (buf1, payload, len);
|
||||||
|
if (m_Owner.GetIdentity ().GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1)
|
||||||
|
{
|
||||||
|
uint8_t hash[32];
|
||||||
|
CryptoPP::SHA256().CalculateDigest (hash, buf1, len);
|
||||||
|
m_Owner.Sign (hash, 32, signature);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_Owner.Sign (buf1, len, signature);
|
||||||
|
|
||||||
|
auto service = m_Owner.GetService ();
|
||||||
|
if (service)
|
||||||
|
service->post (boost::bind (&DatagramDestination::SendMsg, this,
|
||||||
|
CreateDataMessage (buf, len + headerLen), remote));
|
||||||
|
else
|
||||||
|
LogPrint ("Failed to send datagram. Destination is not running");
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatagramDestination::SendMsg (I2NPMessage * msg, const i2p::data::LeaseSet& remote)
|
||||||
|
{
|
||||||
|
auto leases = remote.GetNonExpiredLeases ();
|
||||||
|
if (!leases.empty ())
|
||||||
|
{
|
||||||
|
std::vector<i2p::tunnel::TunnelMessageBlock> msgs;
|
||||||
|
uint32_t i = i2p::context.GetRandomNumberGenerator ().GenerateWord32 (0, leases.size () - 1);
|
||||||
|
auto garlic = m_Owner.WrapMessage (remote, msg, true);
|
||||||
|
msgs.push_back (i2p::tunnel::TunnelMessageBlock
|
||||||
|
{
|
||||||
|
i2p::tunnel::eDeliveryTypeTunnel,
|
||||||
|
leases[i].tunnelGateway, leases[i].tunnelID,
|
||||||
|
garlic
|
||||||
|
});
|
||||||
|
m_Owner.SendTunnelDataMsgs (msgs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrint ("Failed to send datagram. All leases expired");
|
||||||
|
DeleteI2NPMessage (msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatagramDestination::HandleDatagram (const uint8_t * buf, size_t len)
|
||||||
|
{
|
||||||
|
i2p::data::IdentityEx identity;
|
||||||
|
size_t identityLen = identity.FromBuffer (buf, len);
|
||||||
|
const uint8_t * signature = buf + identityLen;
|
||||||
|
size_t headerLen = identityLen + identity.GetSignatureLen ();
|
||||||
|
|
||||||
|
bool verified = false;
|
||||||
|
if (identity.GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1)
|
||||||
|
{
|
||||||
|
uint8_t hash[32];
|
||||||
|
CryptoPP::SHA256().CalculateDigest (hash, buf + headerLen, len - headerLen);
|
||||||
|
verified = identity.Verify (hash, 32, signature);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
verified = identity.Verify (buf + headerLen, len - headerLen, signature);
|
||||||
|
|
||||||
|
if (verified)
|
||||||
|
{
|
||||||
|
// TODO: invoke datagram handler
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint ("Datagram signature verification failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatagramDestination::HandleDataMessagePayload (const uint8_t * buf, size_t len)
|
||||||
|
{
|
||||||
|
// unzip it
|
||||||
|
CryptoPP::Gunzip decompressor;
|
||||||
|
decompressor.Put (buf, len);
|
||||||
|
decompressor.MessageEnd();
|
||||||
|
uint8_t uncompressed[MAX_DATAGRAM_SIZE];
|
||||||
|
auto uncompressedLen = decompressor.MaxRetrievable ();
|
||||||
|
if (uncompressedLen <= MAX_DATAGRAM_SIZE)
|
||||||
|
{
|
||||||
|
decompressor.Get (uncompressed, uncompressedLen);
|
||||||
|
HandleDatagram (uncompressed, uncompressedLen);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint ("Received datagram size ", uncompressedLen, " exceeds max size");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
I2NPMessage * DatagramDestination::CreateDataMessage (const uint8_t * payload, size_t len)
|
||||||
|
{
|
||||||
|
I2NPMessage * msg = NewI2NPMessage ();
|
||||||
|
CryptoPP::Gzip compressor; // default level
|
||||||
|
compressor.Put (payload, len);
|
||||||
|
compressor.MessageEnd();
|
||||||
|
int size = compressor.MaxRetrievable ();
|
||||||
|
uint8_t * buf = msg->GetPayload ();
|
||||||
|
*(uint32_t *)buf = htobe32 (size); // length
|
||||||
|
buf += 4;
|
||||||
|
compressor.Get (buf, size);
|
||||||
|
memset (buf + 4, 0, 4); // source and destination are zeroes
|
||||||
|
buf[9] = i2p::client::PROTOCOL_TYPE_DATAGRAM; // datagram protocol
|
||||||
|
msg->len += size + 4;
|
||||||
|
FillI2NPMessageHeader (msg, eI2NPData);
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
41
Datagram.h
Normal file
41
Datagram.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#ifndef DATAGRAM_H__
|
||||||
|
#define DATAGRAM_H__
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include "LeaseSet.h"
|
||||||
|
#include "I2NPProtocol.h"
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace client
|
||||||
|
{
|
||||||
|
class ClientDestination;
|
||||||
|
}
|
||||||
|
namespace datagram
|
||||||
|
{
|
||||||
|
const size_t MAX_DATAGRAM_SIZE = 32768;
|
||||||
|
class DatagramDestination
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
DatagramDestination (i2p::client::ClientDestination& owner);
|
||||||
|
~DatagramDestination () {};
|
||||||
|
|
||||||
|
void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::LeaseSet& remote);
|
||||||
|
void HandleDataMessagePayload (const uint8_t * buf, size_t len);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
I2NPMessage * CreateDataMessage (const uint8_t * payload, size_t len);
|
||||||
|
void SendMsg (I2NPMessage * msg, const i2p::data::LeaseSet& remote);
|
||||||
|
void HandleDatagram (const uint8_t * buf, size_t len);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
i2p::client::ClientDestination& m_Owner;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
195
Destination.cpp
195
Destination.cpp
|
@ -1,7 +1,6 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cryptopp/dh.h>
|
#include <cryptopp/dh.h>
|
||||||
#include <cryptopp/gzip.h>
|
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "NetDb.h"
|
#include "NetDb.h"
|
||||||
|
@ -13,7 +12,8 @@ namespace client
|
||||||
{
|
{
|
||||||
ClientDestination::ClientDestination (bool isPublic, i2p::data::SigningKeyType sigType):
|
ClientDestination::ClientDestination (bool isPublic, i2p::data::SigningKeyType sigType):
|
||||||
m_IsRunning (false), m_Thread (nullptr), m_Service (nullptr), m_Work (nullptr),
|
m_IsRunning (false), m_Thread (nullptr), m_Service (nullptr), m_Work (nullptr),
|
||||||
m_CurrentOutboundTunnel (nullptr), m_LeaseSet (nullptr), m_IsPublic (isPublic)
|
m_CurrentOutboundTunnel (nullptr), m_LeaseSet (nullptr), m_IsPublic (isPublic),
|
||||||
|
m_DatagramDestination (nullptr)
|
||||||
{
|
{
|
||||||
m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType);
|
m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType);
|
||||||
CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
|
CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
|
||||||
|
@ -21,11 +21,13 @@ namespace client
|
||||||
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (*this, 3); // 3-hops tunnel
|
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (*this, 3); // 3-hops tunnel
|
||||||
if (m_IsPublic)
|
if (m_IsPublic)
|
||||||
LogPrint ("Local address ", GetIdentHash ().ToBase32 (), ".b32.i2p created");
|
LogPrint ("Local address ", GetIdentHash ().ToBase32 (), ".b32.i2p created");
|
||||||
|
m_StreamingDestination = new i2p::stream::StreamingDestination (*this); // TODO:
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientDestination::ClientDestination (const std::string& fullPath, bool isPublic):
|
ClientDestination::ClientDestination (const std::string& fullPath, bool isPublic):
|
||||||
m_IsRunning (false), m_Thread (nullptr), m_Service (nullptr), m_Work (nullptr),
|
m_IsRunning (false), m_Thread (nullptr), m_Service (nullptr), m_Work (nullptr),
|
||||||
m_CurrentOutboundTunnel (nullptr), m_LeaseSet (nullptr), m_IsPublic (isPublic)
|
m_CurrentOutboundTunnel (nullptr), m_LeaseSet (nullptr), m_IsPublic (isPublic),
|
||||||
|
m_DatagramDestination (nullptr)
|
||||||
{
|
{
|
||||||
std::ifstream s(fullPath.c_str (), std::ifstream::binary);
|
std::ifstream s(fullPath.c_str (), std::ifstream::binary);
|
||||||
if (s.is_open ())
|
if (s.is_open ())
|
||||||
|
@ -56,17 +58,20 @@ namespace client
|
||||||
CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
|
CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
|
||||||
dh.GenerateKeyPair(i2p::context.GetRandomNumberGenerator (), m_EncryptionPrivateKey, m_EncryptionPublicKey);
|
dh.GenerateKeyPair(i2p::context.GetRandomNumberGenerator (), m_EncryptionPrivateKey, m_EncryptionPublicKey);
|
||||||
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (*this, 3); // 3-hops tunnel
|
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (*this, 3); // 3-hops tunnel
|
||||||
|
m_StreamingDestination = new i2p::stream::StreamingDestination (*this); // TODO:
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic):
|
ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic):
|
||||||
m_IsRunning (false), m_Thread (nullptr), m_Service (nullptr), m_Work (nullptr),
|
m_IsRunning (false), m_Thread (nullptr), m_Service (nullptr), m_Work (nullptr),
|
||||||
m_Keys (keys), m_CurrentOutboundTunnel (nullptr), m_LeaseSet (nullptr), m_IsPublic (isPublic)
|
m_Keys (keys), m_CurrentOutboundTunnel (nullptr), m_LeaseSet (nullptr), m_IsPublic (isPublic),
|
||||||
|
m_DatagramDestination (nullptr)
|
||||||
{
|
{
|
||||||
CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
|
CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
|
||||||
dh.GenerateKeyPair(i2p::context.GetRandomNumberGenerator (), m_EncryptionPrivateKey, m_EncryptionPublicKey);
|
dh.GenerateKeyPair(i2p::context.GetRandomNumberGenerator (), m_EncryptionPrivateKey, m_EncryptionPublicKey);
|
||||||
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (*this, 3); // 3-hops tunnel
|
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (*this, 3); // 3-hops tunnel
|
||||||
if (m_IsPublic)
|
if (m_IsPublic)
|
||||||
LogPrint ("Local address ", GetIdentHash ().ToBase32 (), ".b32.i2p created");
|
LogPrint ("Local address ", GetIdentHash ().ToBase32 (), ".b32.i2p created");
|
||||||
|
m_StreamingDestination = new i2p::stream::StreamingDestination (*this); // TODO:
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientDestination::~ClientDestination ()
|
ClientDestination::~ClientDestination ()
|
||||||
|
@ -79,6 +84,8 @@ namespace client
|
||||||
delete m_LeaseSet;
|
delete m_LeaseSet;
|
||||||
delete m_Work;
|
delete m_Work;
|
||||||
delete m_Service;
|
delete m_Service;
|
||||||
|
delete m_StreamingDestination;
|
||||||
|
delete m_DatagramDestination;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::Run ()
|
void ClientDestination::Run ()
|
||||||
|
@ -94,10 +101,12 @@ namespace client
|
||||||
m_Pool->SetActive (true);
|
m_Pool->SetActive (true);
|
||||||
m_IsRunning = true;
|
m_IsRunning = true;
|
||||||
m_Thread = new std::thread (std::bind (&ClientDestination::Run, this));
|
m_Thread = new std::thread (std::bind (&ClientDestination::Run, this));
|
||||||
|
m_StreamingDestination->Start ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::Stop ()
|
void ClientDestination::Stop ()
|
||||||
{
|
{
|
||||||
|
m_StreamingDestination->Stop ();
|
||||||
if (m_Pool)
|
if (m_Pool)
|
||||||
i2p::tunnel::tunnels.StopTunnelPool (m_Pool);
|
i2p::tunnel::tunnels.StopTunnelPool (m_Pool);
|
||||||
m_IsRunning = false;
|
m_IsRunning = false;
|
||||||
|
@ -238,135 +247,57 @@ namespace client
|
||||||
uint32_t length = be32toh (*(uint32_t *)buf);
|
uint32_t length = be32toh (*(uint32_t *)buf);
|
||||||
buf += 4;
|
buf += 4;
|
||||||
// we assume I2CP payload
|
// we assume I2CP payload
|
||||||
if (buf[9] == 6) // streaming protocol
|
switch (buf[9])
|
||||||
{
|
|
||||||
// unzip it
|
|
||||||
CryptoPP::Gunzip decompressor;
|
|
||||||
decompressor.Put (buf, length);
|
|
||||||
decompressor.MessageEnd();
|
|
||||||
i2p::stream::Packet * uncompressed = new i2p::stream::Packet;
|
|
||||||
uncompressed->offset = 0;
|
|
||||||
uncompressed->len = decompressor.MaxRetrievable ();
|
|
||||||
if (uncompressed->len <= i2p::stream::MAX_PACKET_SIZE)
|
|
||||||
{
|
|
||||||
decompressor.Get (uncompressed->buf, uncompressed->len);
|
|
||||||
HandleNextPacket (uncompressed);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LogPrint ("Received packet size ", uncompressed->len, " exceeds max packet size. Skipped");
|
|
||||||
decompressor.Skip ();
|
|
||||||
delete uncompressed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LogPrint ("Data: unexpected protocol ", buf[9]);
|
|
||||||
}
|
|
||||||
|
|
||||||
I2NPMessage * ClientDestination::CreateDataMessage (const uint8_t * payload, size_t len)
|
|
||||||
{
|
|
||||||
I2NPMessage * msg = NewI2NPShortMessage ();
|
|
||||||
CryptoPP::Gzip compressor;
|
|
||||||
if (len <= i2p::stream::COMPRESSION_THRESHOLD_SIZE)
|
|
||||||
compressor.SetDeflateLevel (CryptoPP::Gzip::MIN_DEFLATE_LEVEL);
|
|
||||||
else
|
|
||||||
compressor.SetDeflateLevel (CryptoPP::Gzip::DEFAULT_DEFLATE_LEVEL);
|
|
||||||
compressor.Put (payload, len);
|
|
||||||
compressor.MessageEnd();
|
|
||||||
int size = compressor.MaxRetrievable ();
|
|
||||||
uint8_t * buf = msg->GetPayload ();
|
|
||||||
*(uint32_t *)buf = htobe32 (size); // length
|
|
||||||
buf += 4;
|
|
||||||
compressor.Get (buf, size);
|
|
||||||
memset (buf + 4, 0, 4); // source and destination ports. TODO: fill with proper values later
|
|
||||||
buf[9] = 6; // streaming protocol
|
|
||||||
msg->len += size + 4;
|
|
||||||
FillI2NPMessageHeader (msg, eI2NPData);
|
|
||||||
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace stream
|
|
||||||
{
|
|
||||||
|
|
||||||
void StreamingDestination::Start ()
|
|
||||||
{
|
|
||||||
ClientDestination::Start ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void StreamingDestination::Stop ()
|
|
||||||
{
|
|
||||||
ResetAcceptor ();
|
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> l(m_StreamsMutex);
|
case PROTOCOL_TYPE_STREAMING:
|
||||||
for (auto it: m_Streams)
|
// streaming protocol
|
||||||
delete it.second;
|
if (m_StreamingDestination)
|
||||||
m_Streams.clear ();
|
m_StreamingDestination->HandleDataMessagePayload (buf, length);
|
||||||
}
|
|
||||||
ClientDestination::Stop ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void StreamingDestination::HandleNextPacket (Packet * packet)
|
|
||||||
{
|
|
||||||
uint32_t sendStreamID = packet->GetSendStreamID ();
|
|
||||||
if (sendStreamID)
|
|
||||||
{
|
|
||||||
auto it = m_Streams.find (sendStreamID);
|
|
||||||
if (it != m_Streams.end ())
|
|
||||||
it->second->HandleNextPacket (packet);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LogPrint ("Unknown stream ", sendStreamID);
|
|
||||||
delete packet;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // new incoming stream
|
|
||||||
{
|
|
||||||
auto incomingStream = CreateNewIncomingStream ();
|
|
||||||
incomingStream->HandleNextPacket (packet);
|
|
||||||
if (m_Acceptor != nullptr)
|
|
||||||
m_Acceptor (incomingStream);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LogPrint ("Acceptor for incoming stream is not set");
|
|
||||||
DeleteStream (incomingStream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream * StreamingDestination::CreateNewOutgoingStream (const i2p::data::LeaseSet& remote)
|
|
||||||
{
|
|
||||||
Stream * s = new Stream (*GetService (), *this, remote);
|
|
||||||
std::unique_lock<std::mutex> l(m_StreamsMutex);
|
|
||||||
m_Streams[s->GetRecvStreamID ()] = s;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream * StreamingDestination::CreateNewIncomingStream ()
|
|
||||||
{
|
|
||||||
Stream * s = new Stream (*GetService (), *this);
|
|
||||||
std::unique_lock<std::mutex> l(m_StreamsMutex);
|
|
||||||
m_Streams[s->GetRecvStreamID ()] = s;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StreamingDestination::DeleteStream (Stream * stream)
|
|
||||||
{
|
|
||||||
if (stream)
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> l(m_StreamsMutex);
|
|
||||||
auto it = m_Streams.find (stream->GetRecvStreamID ());
|
|
||||||
if (it != m_Streams.end ())
|
|
||||||
{
|
|
||||||
m_Streams.erase (it);
|
|
||||||
if (GetService ())
|
|
||||||
GetService ()->post ([stream](void) { delete stream; });
|
|
||||||
else
|
else
|
||||||
delete stream;
|
LogPrint ("Missing streaming destination");
|
||||||
}
|
break;
|
||||||
}
|
case PROTOCOL_TYPE_DATAGRAM:
|
||||||
|
// datagram protocol
|
||||||
|
if (m_DatagramDestination)
|
||||||
|
m_DatagramDestination->HandleDataMessagePayload (buf, length);
|
||||||
|
else
|
||||||
|
LogPrint ("Missing streaming destination");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LogPrint ("Data: unexpected protocol ", buf[9]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
i2p::stream::Stream * ClientDestination::CreateStream (const i2p::data::LeaseSet& remote, int port)
|
||||||
|
{
|
||||||
|
if (m_StreamingDestination)
|
||||||
|
return m_StreamingDestination->CreateNewOutgoingStream (remote, port);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientDestination::AcceptStreams (const std::function<void (i2p::stream::Stream *)>& acceptor)
|
||||||
|
{
|
||||||
|
if (m_StreamingDestination)
|
||||||
|
m_StreamingDestination->SetAcceptor (acceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientDestination::StopAcceptingStreams ()
|
||||||
|
{
|
||||||
|
if (m_StreamingDestination)
|
||||||
|
m_StreamingDestination->ResetAcceptor ();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClientDestination::IsAcceptingStreams () const
|
||||||
|
{
|
||||||
|
if (m_StreamingDestination)
|
||||||
|
return m_StreamingDestination->IsAcceptorSet ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientDestination::CreateDatagramDestination ()
|
||||||
|
{
|
||||||
|
if (!m_DatagramDestination)
|
||||||
|
m_DatagramDestination = new i2p::datagram::DatagramDestination (*this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,11 +9,16 @@
|
||||||
#include "LeaseSet.h"
|
#include "LeaseSet.h"
|
||||||
#include "Garlic.h"
|
#include "Garlic.h"
|
||||||
#include "Streaming.h"
|
#include "Streaming.h"
|
||||||
|
#include "Datagram.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace client
|
namespace client
|
||||||
{
|
{
|
||||||
|
const uint8_t PROTOCOL_TYPE_STREAMING = 6;
|
||||||
|
const uint8_t PROTOCOL_TYPE_DATAGRAM = 17;
|
||||||
|
const uint8_t PROTOCOL_TYPE_RAW = 18;
|
||||||
|
|
||||||
class ClientDestination: public i2p::garlic::GarlicDestination
|
class ClientDestination: public i2p::garlic::GarlicDestination
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -34,6 +39,17 @@ namespace client
|
||||||
const i2p::data::LeaseSet * FindLeaseSet (const i2p::data::IdentHash& ident);
|
const i2p::data::LeaseSet * FindLeaseSet (const i2p::data::IdentHash& ident);
|
||||||
void SendTunnelDataMsgs (const std::vector<i2p::tunnel::TunnelMessageBlock>& msgs);
|
void SendTunnelDataMsgs (const std::vector<i2p::tunnel::TunnelMessageBlock>& msgs);
|
||||||
|
|
||||||
|
// streaming
|
||||||
|
i2p::stream::StreamingDestination * GetStreamingDestination () const { return m_StreamingDestination; };
|
||||||
|
i2p::stream::Stream * CreateStream (const i2p::data::LeaseSet& remote, int port = 0);
|
||||||
|
void AcceptStreams (const std::function<void (i2p::stream::Stream *)>& acceptor);
|
||||||
|
void StopAcceptingStreams ();
|
||||||
|
bool IsAcceptingStreams () const;
|
||||||
|
|
||||||
|
// datagram
|
||||||
|
i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; };
|
||||||
|
void CreateDatagramDestination ();
|
||||||
|
|
||||||
// implements LocalDestination
|
// implements LocalDestination
|
||||||
const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; };
|
const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; };
|
||||||
const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; };
|
const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; };
|
||||||
|
@ -50,11 +66,6 @@ namespace client
|
||||||
|
|
||||||
// I2CP
|
// I2CP
|
||||||
void HandleDataMessage (const uint8_t * buf, size_t len);
|
void HandleDataMessage (const uint8_t * buf, size_t len);
|
||||||
I2NPMessage * CreateDataMessage (const uint8_t * payload, size_t len);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
virtual void HandleNextPacket (i2p::stream::Packet * packet) = 0; // TODO
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -77,55 +88,15 @@ namespace client
|
||||||
i2p::data::LeaseSet * m_LeaseSet;
|
i2p::data::LeaseSet * m_LeaseSet;
|
||||||
bool m_IsPublic;
|
bool m_IsPublic;
|
||||||
|
|
||||||
|
i2p::stream::StreamingDestination * m_StreamingDestination;
|
||||||
|
i2p::datagram::DatagramDestination * m_DatagramDestination;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// for HTTP only
|
// for HTTP only
|
||||||
int GetNumRemoteLeaseSets () const { return m_RemoteLeaseSets.size (); };
|
int GetNumRemoteLeaseSets () const { return m_RemoteLeaseSets.size (); };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace stream
|
|
||||||
{
|
|
||||||
class StreamingDestination: public i2p::client::ClientDestination
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
StreamingDestination (bool isPublic, i2p::data::SigningKeyType sigType):
|
|
||||||
ClientDestination (isPublic, sigType) {};
|
|
||||||
StreamingDestination (const std::string& fullPath, bool isPublic):
|
|
||||||
ClientDestination (fullPath, isPublic) {};
|
|
||||||
StreamingDestination (const i2p::data::PrivateKeys& keys, bool isPublic):
|
|
||||||
ClientDestination (keys, isPublic) {};
|
|
||||||
~StreamingDestination () {};
|
|
||||||
|
|
||||||
void Start ();
|
|
||||||
void Stop ();
|
|
||||||
|
|
||||||
Stream * CreateNewOutgoingStream (const i2p::data::LeaseSet& remote);
|
|
||||||
void DeleteStream (Stream * stream);
|
|
||||||
void SetAcceptor (const std::function<void (Stream *)>& acceptor) { m_Acceptor = acceptor; };
|
|
||||||
void ResetAcceptor () { m_Acceptor = nullptr; };
|
|
||||||
bool IsAcceptorSet () const { return m_Acceptor != nullptr; };
|
|
||||||
|
|
||||||
// ClientDestination
|
|
||||||
void HandleNextPacket (Packet * packet);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
Stream * CreateNewIncomingStream ();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
std::mutex m_StreamsMutex;
|
|
||||||
std::map<uint32_t, Stream *> m_Streams;
|
|
||||||
std::function<void (Stream *)> m_Acceptor;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
// for HTTP only
|
|
||||||
const decltype(m_Streams)& GetStreams () const { return m_Streams; };
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <boost/regex.hpp>
|
#include <boost/regex.hpp>
|
||||||
|
|
||||||
#include "NetDb.h"
|
#include "ClientContext.h"
|
||||||
#include "HTTPProxy.h"
|
#include "HTTPProxy.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
|
@ -52,10 +52,11 @@ namespace proxy
|
||||||
}
|
}
|
||||||
path=m[4].str();
|
path=m[4].str();
|
||||||
}
|
}
|
||||||
LogPrint("server is: ",server, "\n path is: ",path);
|
LogPrint("server is: ",server, " port is: ", port, "\n path is: ",path);
|
||||||
r.uri = path;
|
r.uri = path;
|
||||||
r.method = method;
|
r.method = method;
|
||||||
r.host = server;
|
r.host = server;
|
||||||
|
r.port = boost::lexical_cast<int>(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -73,12 +74,12 @@ namespace proxy
|
||||||
{
|
{
|
||||||
LogPrint ("Jump service for ", r.host, " found. Inserting to address book");
|
LogPrint ("Jump service for ", r.host, " found. Inserting to address book");
|
||||||
auto base64 = r.uri.substr (addressPos + 1);
|
auto base64 = r.uri.substr (addressPos + 1);
|
||||||
i2p::data::netdb.GetAddressBook ().InsertAddress (r.host, base64);
|
i2p::client::context.GetAddressBook ().InsertAddress (r.host, base64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LogPrint("Requesting ", r.host, " with path ", r.uri, " and method ", r.method);
|
LogPrint("Requesting ", r.host, ":", r.port, " with path ", r.uri, " and method ", r.method);
|
||||||
SendToAddress (r.host, m_Buffer, m_BufferLen);
|
SendToAddress (r.host, r.port, m_Buffer, m_BufferLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -517,7 +517,7 @@ namespace util
|
||||||
if (m_Stream)
|
if (m_Stream)
|
||||||
{
|
{
|
||||||
m_Stream->Close ();
|
m_Stream->Close ();
|
||||||
i2p::client::context.GetSharedLocalDestination ()->DeleteStream (m_Stream);
|
i2p::stream::DeleteStream (m_Stream);
|
||||||
m_Stream = nullptr;
|
m_Stream = nullptr;
|
||||||
}
|
}
|
||||||
m_Socket->close ();
|
m_Socket->close ();
|
||||||
|
@ -644,7 +644,10 @@ namespace util
|
||||||
switch (address.transportStyle)
|
switch (address.transportStyle)
|
||||||
{
|
{
|
||||||
case i2p::data::RouterInfo::eTransportNTCP:
|
case i2p::data::RouterInfo::eTransportNTCP:
|
||||||
s << "NTCP ";
|
if (address.host.is_v6 ())
|
||||||
|
s << "NTCP6 ";
|
||||||
|
else
|
||||||
|
s << "NTCP ";
|
||||||
break;
|
break;
|
||||||
case i2p::data::RouterInfo::eTransportSSU:
|
case i2p::data::RouterInfo::eTransportSSU:
|
||||||
s << "SSU ";
|
s << "SSU ";
|
||||||
|
@ -699,14 +702,14 @@ namespace util
|
||||||
void HTTPConnection::ShowTransports (std::stringstream& s)
|
void HTTPConnection::ShowTransports (std::stringstream& s)
|
||||||
{
|
{
|
||||||
s << "NTCP<br>";
|
s << "NTCP<br>";
|
||||||
for (auto it: i2p::transports.GetNTCPSessions ())
|
for (auto it: i2p::transport::transports.GetNTCPSessions ())
|
||||||
{
|
{
|
||||||
// RouterInfo of incoming connection doesn't have address
|
|
||||||
bool outgoing = it.second->GetRemoteRouterInfo ().GetNTCPAddress ();
|
|
||||||
if (it.second->IsEstablished ())
|
if (it.second->IsEstablished ())
|
||||||
{
|
{
|
||||||
|
// incoming connection doesn't have remote RI
|
||||||
|
bool outgoing = it.second->GetRemoteRouter ();
|
||||||
if (outgoing) s << "-->";
|
if (outgoing) s << "-->";
|
||||||
s << it.second->GetRemoteRouterInfo ().GetIdentHashAbbreviation () << ": "
|
s << it.second->GetRemoteIdentity ().GetIdentHash ().ToBase64 ().substr (0, 4) << ": "
|
||||||
<< it.second->GetSocket ().remote_endpoint().address ().to_string ();
|
<< it.second->GetSocket ().remote_endpoint().address ().to_string ();
|
||||||
if (!outgoing) s << "-->";
|
if (!outgoing) s << "-->";
|
||||||
s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
|
s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
|
||||||
|
@ -714,7 +717,7 @@ namespace util
|
||||||
}
|
}
|
||||||
s << std::endl;
|
s << std::endl;
|
||||||
}
|
}
|
||||||
auto ssuServer = i2p::transports.GetSSUServer ();
|
auto ssuServer = i2p::transport::transports.GetSSUServer ();
|
||||||
if (ssuServer)
|
if (ssuServer)
|
||||||
{
|
{
|
||||||
s << "<br>SSU<br>";
|
s << "<br>SSU<br>";
|
||||||
|
@ -813,7 +816,7 @@ namespace util
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s << "<br><b>Streams:</b><br>";
|
s << "<br><b>Streams:</b><br>";
|
||||||
for (auto it: dest->GetStreams ())
|
for (auto it: dest->GetStreamingDestination ()->GetStreams ())
|
||||||
{
|
{
|
||||||
s << it.first << "->" << it.second->GetRemoteIdentity ().GetIdentHash ().ToBase32 () << ".b32.i2p ";
|
s << it.first << "->" << it.second->GetRemoteIdentity ().GetIdentHash ().ToBase32 () << ".b32.i2p ";
|
||||||
s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
|
s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
|
||||||
|
@ -839,45 +842,56 @@ namespace util
|
||||||
{
|
{
|
||||||
std::string request = "GET " + uri + " HTTP/1.1\r\nHost:" + address + "\r\n";
|
std::string request = "GET " + uri + " HTTP/1.1\r\nHost:" + address + "\r\n";
|
||||||
LogPrint("HTTP Client Request: ", request);
|
LogPrint("HTTP Client Request: ", request);
|
||||||
SendToAddress (address, request.c_str (), request.size ());
|
SendToAddress (address, 80, request.c_str (), request.size ());
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTPConnection::SendToAddress (const std::string& address, const char * buf, size_t len)
|
void HTTPConnection::SendToAddress (const std::string& address, int port, const char * buf, size_t len)
|
||||||
{
|
{
|
||||||
i2p::data::IdentHash destination;
|
i2p::data::IdentHash destination;
|
||||||
if (!i2p::data::netdb.GetAddressBook ().GetIdentHash (address, destination))
|
if (!i2p::client::context.GetAddressBook ().GetIdentHash (address, destination))
|
||||||
{
|
{
|
||||||
LogPrint ("Unknown address ", address);
|
LogPrint ("Unknown address ", address);
|
||||||
SendReply ("<html>" + itoopieImage + "<br>Unknown address " + address + "</html>", 404);
|
SendReply ("<html>" + itoopieImage + "<br>Unknown address " + address + "</html>", 404);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SendToDestination (destination, buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HTTPConnection::SendToDestination (const i2p::data::IdentHash& destination, const char * buf, size_t len)
|
|
||||||
{
|
|
||||||
auto leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (destination);
|
auto leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (destination);
|
||||||
if (!leaseSet || !leaseSet->HasNonExpiredLeases ())
|
if (leaseSet && leaseSet->HasNonExpiredLeases ())
|
||||||
|
SendToDestination (leaseSet, port, buf, len);
|
||||||
|
else
|
||||||
{
|
{
|
||||||
i2p::data::netdb.RequestDestination (destination, true, i2p::client::context.GetSharedLocalDestination ()->GetTunnelPool ());
|
i2p::data::netdb.RequestDestination (destination, true, i2p::client::context.GetSharedLocalDestination ()->GetTunnelPool ());
|
||||||
std::this_thread::sleep_for (std::chrono::seconds(10)); // wait for 10 seconds
|
m_Timer.expires_from_now (boost::posix_time::seconds(HTTP_DESTINATION_REQUEST_TIMEOUT));
|
||||||
leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (destination);
|
m_Timer.async_wait (boost::bind (&HTTPConnection::HandleDestinationRequestTimeout,
|
||||||
if (!leaseSet || !leaseSet->HasNonExpiredLeases ()) // still no LeaseSet
|
this, boost::asio::placeholders::error, destination, port, buf, len));
|
||||||
{
|
|
||||||
SendReply (leaseSet ? "<html>" + itoopieImage + "<br>Leases expired</html>" : "<html>" + itoopieImage + "LeaseSet not found</html>", 504);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTTPConnection::HandleDestinationRequestTimeout (const boost::system::error_code& ecode,
|
||||||
|
i2p::data::IdentHash destination, int port, const char * buf, size_t len)
|
||||||
|
{
|
||||||
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
|
{
|
||||||
|
auto leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (destination);
|
||||||
|
if (leaseSet && leaseSet->HasNonExpiredLeases ())
|
||||||
|
SendToDestination (leaseSet, port, buf, len);
|
||||||
|
else
|
||||||
|
// still no LeaseSet
|
||||||
|
SendReply (leaseSet ? "<html>" + itoopieImage + "<br>Leases expired</html>" : "<html>" + itoopieImage + "LeaseSet not found</html>", 504);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTTPConnection::SendToDestination (const i2p::data::LeaseSet * remote, int port, const char * buf, size_t len)
|
||||||
|
{
|
||||||
if (!m_Stream)
|
if (!m_Stream)
|
||||||
m_Stream = i2p::client::context.GetSharedLocalDestination ()->CreateNewOutgoingStream (*leaseSet);
|
m_Stream = i2p::client::context.GetSharedLocalDestination ()->CreateStream (*remote, port);
|
||||||
if (m_Stream)
|
if (m_Stream)
|
||||||
{
|
{
|
||||||
m_Stream->Send ((uint8_t *)buf, len);
|
m_Stream->Send ((uint8_t *)buf, len);
|
||||||
AsyncStreamReceive ();
|
AsyncStreamReceive ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTPConnection::AsyncStreamReceive ()
|
void HTTPConnection::AsyncStreamReceive ()
|
||||||
{
|
{
|
||||||
if (m_Stream)
|
if (m_Stream)
|
||||||
|
|
13
HTTPServer.h
13
HTTPServer.h
|
@ -5,6 +5,7 @@
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/array.hpp>
|
#include <boost/array.hpp>
|
||||||
|
#include "LeaseSet.h"
|
||||||
#include "Streaming.h"
|
#include "Streaming.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
|
@ -12,6 +13,7 @@ namespace i2p
|
||||||
namespace util
|
namespace util
|
||||||
{
|
{
|
||||||
const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192;
|
const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192;
|
||||||
|
const int HTTP_DESTINATION_REQUEST_TIMEOUT = 10; // in seconds
|
||||||
class HTTPConnection
|
class HTTPConnection
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
@ -27,6 +29,7 @@ namespace util
|
||||||
std::string method;
|
std::string method;
|
||||||
std::string uri;
|
std::string uri;
|
||||||
std::string host;
|
std::string host;
|
||||||
|
int port;
|
||||||
int http_version_major;
|
int http_version_major;
|
||||||
int http_version_minor;
|
int http_version_minor;
|
||||||
std::vector<header> headers;
|
std::vector<header> headers;
|
||||||
|
@ -43,7 +46,8 @@ namespace util
|
||||||
public:
|
public:
|
||||||
|
|
||||||
HTTPConnection (boost::asio::ip::tcp::socket * socket):
|
HTTPConnection (boost::asio::ip::tcp::socket * socket):
|
||||||
m_Socket (socket), m_Stream (nullptr), m_BufferLen (0) { Receive (); };
|
m_Socket (socket), m_Timer (socket->get_io_service ()),
|
||||||
|
m_Stream (nullptr), m_BufferLen (0) { Receive (); };
|
||||||
virtual ~HTTPConnection() { delete m_Socket; }
|
virtual ~HTTPConnection() { delete m_Socket; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -74,6 +78,7 @@ namespace util
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
boost::asio::ip::tcp::socket * m_Socket;
|
boost::asio::ip::tcp::socket * m_Socket;
|
||||||
|
boost::asio::deadline_timer m_Timer;
|
||||||
i2p::stream::Stream * m_Stream;
|
i2p::stream::Stream * m_Stream;
|
||||||
char m_Buffer[HTTP_CONNECTION_BUFFER_SIZE + 1], m_StreamBuffer[HTTP_CONNECTION_BUFFER_SIZE + 1];
|
char m_Buffer[HTTP_CONNECTION_BUFFER_SIZE + 1], m_StreamBuffer[HTTP_CONNECTION_BUFFER_SIZE + 1];
|
||||||
size_t m_BufferLen;
|
size_t m_BufferLen;
|
||||||
|
@ -84,8 +89,10 @@ namespace util
|
||||||
|
|
||||||
virtual void RunRequest ();
|
virtual void RunRequest ();
|
||||||
void HandleDestinationRequest(const std::string& address, const std::string& uri);
|
void HandleDestinationRequest(const std::string& address, const std::string& uri);
|
||||||
void SendToAddress (const std::string& address, const char * buf, size_t len);
|
void SendToAddress (const std::string& address, int port, const char * buf, size_t len);
|
||||||
void SendToDestination (const i2p::data::IdentHash& destination, const char * buf, size_t len);
|
void HandleDestinationRequestTimeout (const boost::system::error_code& ecode,
|
||||||
|
i2p::data::IdentHash destination, int port, const char * buf, size_t len);
|
||||||
|
void SendToDestination (const i2p::data::LeaseSet * remote, int port, const char * buf, size_t len);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -13,9 +13,10 @@
|
||||||
#include "Garlic.h"
|
#include "Garlic.h"
|
||||||
#include "I2NPProtocol.h"
|
#include "I2NPProtocol.h"
|
||||||
|
|
||||||
|
using namespace i2p::transport;
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
|
|
||||||
I2NPMessage * NewI2NPMessage ()
|
I2NPMessage * NewI2NPMessage ()
|
||||||
{
|
{
|
||||||
return new I2NPMessageBuffer<I2NP_MAX_MESSAGE_SIZE>();
|
return new I2NPMessageBuffer<I2NP_MAX_MESSAGE_SIZE>();
|
||||||
|
@ -289,7 +290,7 @@ namespace i2p
|
||||||
{
|
{
|
||||||
LogPrint ("Record ",i," is ours");
|
LogPrint ("Record ",i," is ours");
|
||||||
|
|
||||||
i2p::crypto::ElGamalDecrypt (i2p::context.GetPrivateKey (), records[i].encrypted, (uint8_t *)&clearText);
|
i2p::crypto::ElGamalDecrypt (i2p::context.GetEncryptionPrivateKey (), records[i].encrypted, (uint8_t *)&clearText);
|
||||||
// replace record to reply
|
// replace record to reply
|
||||||
I2NPBuildResponseRecord * reply = (I2NPBuildResponseRecord *)(records + i);
|
I2NPBuildResponseRecord * reply = (I2NPBuildResponseRecord *)(records + i);
|
||||||
if (i2p::context.AcceptsTunnels ())
|
if (i2p::context.AcceptsTunnels ())
|
||||||
|
@ -353,13 +354,13 @@ namespace i2p
|
||||||
if (clearText.flag & 0x40) // we are endpoint of outboud tunnel
|
if (clearText.flag & 0x40) // we are endpoint of outboud tunnel
|
||||||
{
|
{
|
||||||
// so we send it to reply tunnel
|
// so we send it to reply tunnel
|
||||||
i2p::transports.SendMessage (clearText.nextIdent,
|
transports.SendMessage (clearText.nextIdent,
|
||||||
CreateTunnelGatewayMsg (be32toh (clearText.nextTunnel),
|
CreateTunnelGatewayMsg (be32toh (clearText.nextTunnel),
|
||||||
eI2NPVariableTunnelBuildReply, buf, len,
|
eI2NPVariableTunnelBuildReply, buf, len,
|
||||||
be32toh (clearText.nextMessageID)));
|
be32toh (clearText.nextMessageID)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
i2p::transports.SendMessage (clearText.nextIdent,
|
transports.SendMessage (clearText.nextIdent,
|
||||||
CreateI2NPMessage (eI2NPVariableTunnelBuild, buf, len, be32toh (clearText.nextMessageID)));
|
CreateI2NPMessage (eI2NPVariableTunnelBuild, buf, len, be32toh (clearText.nextMessageID)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -373,13 +374,13 @@ namespace i2p
|
||||||
if (clearText.flag & 0x40) // we are endpoint of outbound tunnel
|
if (clearText.flag & 0x40) // we are endpoint of outbound tunnel
|
||||||
{
|
{
|
||||||
// so we send it to reply tunnel
|
// so we send it to reply tunnel
|
||||||
i2p::transports.SendMessage (clearText.nextIdent,
|
transports.SendMessage (clearText.nextIdent,
|
||||||
CreateTunnelGatewayMsg (be32toh (clearText.nextTunnel),
|
CreateTunnelGatewayMsg (be32toh (clearText.nextTunnel),
|
||||||
eI2NPTunnelBuildReply, buf, len,
|
eI2NPTunnelBuildReply, buf, len,
|
||||||
be32toh (clearText.nextMessageID)));
|
be32toh (clearText.nextMessageID)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
i2p::transports.SendMessage (clearText.nextIdent,
|
transports.SendMessage (clearText.nextIdent,
|
||||||
CreateI2NPMessage (eI2NPTunnelBuild, buf, len, be32toh (clearText.nextMessageID)));
|
CreateI2NPMessage (eI2NPTunnelBuild, buf, len, be32toh (clearText.nextMessageID)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace client
|
||||||
boost::asio::ip::tcp::socket * socket, const i2p::data::LeaseSet * leaseSet):
|
boost::asio::ip::tcp::socket * socket, const i2p::data::LeaseSet * leaseSet):
|
||||||
m_Socket (socket), m_Owner (owner)
|
m_Socket (socket), m_Owner (owner)
|
||||||
{
|
{
|
||||||
m_Stream = m_Owner->GetLocalDestination ()->CreateNewOutgoingStream (*leaseSet);
|
m_Stream = m_Owner->GetLocalDestination ()->CreateStream (*leaseSet);
|
||||||
m_Stream->Send (m_Buffer, 0); // connect
|
m_Stream->Send (m_Buffer, 0); // connect
|
||||||
StreamReceive ();
|
StreamReceive ();
|
||||||
Receive ();
|
Receive ();
|
||||||
|
@ -39,7 +39,7 @@ namespace client
|
||||||
if (m_Stream)
|
if (m_Stream)
|
||||||
{
|
{
|
||||||
m_Stream->Close ();
|
m_Stream->Close ();
|
||||||
m_Owner->GetLocalDestination ()->DeleteStream (m_Stream);
|
i2p::stream::DeleteStream (m_Stream);
|
||||||
m_Stream = nullptr;
|
m_Stream = nullptr;
|
||||||
}
|
}
|
||||||
m_Socket->close ();
|
m_Socket->close ();
|
||||||
|
@ -115,7 +115,7 @@ namespace client
|
||||||
if (ecode != boost::asio::error::operation_aborted)
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
{
|
{
|
||||||
if (m_Stream) m_Stream->Close ();
|
if (m_Stream) m_Stream->Close ();
|
||||||
m_Owner->GetLocalDestination ()->DeleteStream (m_Stream);
|
i2p::stream::DeleteStream (m_Stream);
|
||||||
m_Stream = nullptr;
|
m_Stream = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -145,7 +145,7 @@ namespace client
|
||||||
}
|
}
|
||||||
|
|
||||||
I2PClientTunnel::I2PClientTunnel (boost::asio::io_service& service, const std::string& destination,
|
I2PClientTunnel::I2PClientTunnel (boost::asio::io_service& service, const std::string& destination,
|
||||||
int port, i2p::stream::StreamingDestination * localDestination):
|
int port, ClientDestination * localDestination):
|
||||||
I2PTunnel (service, localDestination ? localDestination :
|
I2PTunnel (service, localDestination ? localDestination :
|
||||||
i2p::client::context.CreateNewLocalDestination (false, i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256)),
|
i2p::client::context.CreateNewLocalDestination (false, i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256)),
|
||||||
m_Acceptor (service, boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), port)),
|
m_Acceptor (service, boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), port)),
|
||||||
|
@ -162,7 +162,7 @@ namespace client
|
||||||
void I2PClientTunnel::Start ()
|
void I2PClientTunnel::Start ()
|
||||||
{
|
{
|
||||||
i2p::data::IdentHash identHash;
|
i2p::data::IdentHash identHash;
|
||||||
if (i2p::data::netdb.GetAddressBook ().GetIdentHash (m_Destination, identHash))
|
if (i2p::client::context.GetAddressBook ().GetIdentHash (m_Destination, identHash))
|
||||||
m_DestinationIdentHash = new i2p::data::IdentHash (identHash);
|
m_DestinationIdentHash = new i2p::data::IdentHash (identHash);
|
||||||
if (!m_DestinationIdentHash)
|
if (!m_DestinationIdentHash)
|
||||||
LogPrint ("I2PTunnel unknown destination ", m_Destination);
|
LogPrint ("I2PTunnel unknown destination ", m_Destination);
|
||||||
|
@ -192,7 +192,7 @@ namespace client
|
||||||
if (!m_DestinationIdentHash)
|
if (!m_DestinationIdentHash)
|
||||||
{
|
{
|
||||||
i2p::data::IdentHash identHash;
|
i2p::data::IdentHash identHash;
|
||||||
if (i2p::data::netdb.GetAddressBook ().GetIdentHash (m_Destination, identHash))
|
if (i2p::client::context.GetAddressBook ().GetIdentHash (m_Destination, identHash))
|
||||||
m_DestinationIdentHash = new i2p::data::IdentHash (identHash);
|
m_DestinationIdentHash = new i2p::data::IdentHash (identHash);
|
||||||
}
|
}
|
||||||
if (m_DestinationIdentHash)
|
if (m_DestinationIdentHash)
|
||||||
|
@ -251,7 +251,7 @@ namespace client
|
||||||
}
|
}
|
||||||
|
|
||||||
I2PServerTunnel::I2PServerTunnel (boost::asio::io_service& service, const std::string& address, int port,
|
I2PServerTunnel::I2PServerTunnel (boost::asio::io_service& service, const std::string& address, int port,
|
||||||
i2p::stream::StreamingDestination * localDestination): I2PTunnel (service, localDestination),
|
ClientDestination * localDestination): I2PTunnel (service, localDestination),
|
||||||
m_Endpoint (boost::asio::ip::address::from_string (address), port)
|
m_Endpoint (boost::asio::ip::address::from_string (address), port)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -270,7 +270,7 @@ namespace client
|
||||||
{
|
{
|
||||||
auto localDestination = GetLocalDestination ();
|
auto localDestination = GetLocalDestination ();
|
||||||
if (localDestination)
|
if (localDestination)
|
||||||
localDestination->SetAcceptor (std::bind (&I2PServerTunnel::HandleAccept, this, std::placeholders::_1));
|
localDestination->AcceptStreams (std::bind (&I2PServerTunnel::HandleAccept, this, std::placeholders::_1));
|
||||||
else
|
else
|
||||||
LogPrint ("Local destination not set for server tunnel");
|
LogPrint ("Local destination not set for server tunnel");
|
||||||
}
|
}
|
||||||
|
|
13
I2PTunnel.h
13
I2PTunnel.h
|
@ -6,6 +6,7 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
|
#include "Destination.h"
|
||||||
#include "Streaming.h"
|
#include "Streaming.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
|
@ -51,22 +52,22 @@ namespace client
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
I2PTunnel (boost::asio::io_service& service, i2p::stream::StreamingDestination * localDestination):
|
I2PTunnel (boost::asio::io_service& service, ClientDestination * localDestination):
|
||||||
m_Service (service), m_LocalDestination (localDestination) {};
|
m_Service (service), m_LocalDestination (localDestination) {};
|
||||||
virtual ~I2PTunnel () { ClearConnections (); };
|
virtual ~I2PTunnel () { ClearConnections (); };
|
||||||
|
|
||||||
void AddConnection (I2PTunnelConnection * conn);
|
void AddConnection (I2PTunnelConnection * conn);
|
||||||
void RemoveConnection (I2PTunnelConnection * conn);
|
void RemoveConnection (I2PTunnelConnection * conn);
|
||||||
void ClearConnections ();
|
void ClearConnections ();
|
||||||
i2p::stream::StreamingDestination * GetLocalDestination () { return m_LocalDestination; };
|
ClientDestination * GetLocalDestination () { return m_LocalDestination; };
|
||||||
void SetLocalDestination (i2p::stream::StreamingDestination * dest) { m_LocalDestination = dest; };
|
void SetLocalDestination (ClientDestination * dest) { m_LocalDestination = dest; };
|
||||||
|
|
||||||
boost::asio::io_service& GetService () { return m_Service; };
|
boost::asio::io_service& GetService () { return m_Service; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
boost::asio::io_service& m_Service;
|
boost::asio::io_service& m_Service;
|
||||||
i2p::stream::StreamingDestination * m_LocalDestination;
|
ClientDestination * m_LocalDestination;
|
||||||
std::set<I2PTunnelConnection *> m_Connections;
|
std::set<I2PTunnelConnection *> m_Connections;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -75,7 +76,7 @@ namespace client
|
||||||
public:
|
public:
|
||||||
|
|
||||||
I2PClientTunnel (boost::asio::io_service& service, const std::string& destination, int port,
|
I2PClientTunnel (boost::asio::io_service& service, const std::string& destination, int port,
|
||||||
i2p::stream::StreamingDestination * localDestination = nullptr);
|
ClientDestination * localDestination = nullptr);
|
||||||
~I2PClientTunnel ();
|
~I2PClientTunnel ();
|
||||||
|
|
||||||
void Start ();
|
void Start ();
|
||||||
|
@ -102,7 +103,7 @@ namespace client
|
||||||
public:
|
public:
|
||||||
|
|
||||||
I2PServerTunnel (boost::asio::io_service& service, const std::string& address, int port,
|
I2PServerTunnel (boost::asio::io_service& service, const std::string& address, int port,
|
||||||
i2p::stream::StreamingDestination * localDestination);
|
ClientDestination * localDestination);
|
||||||
|
|
||||||
void Start ();
|
void Start ();
|
||||||
void Stop ();
|
void Stop ();
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <cryptopp/sha.h>
|
#include <cryptopp/sha.h>
|
||||||
#include <cryptopp/osrng.h>
|
#include <cryptopp/osrng.h>
|
||||||
#include <cryptopp/dh.h>
|
|
||||||
#include <cryptopp/dsa.h>
|
#include <cryptopp/dsa.h>
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
#include "CryptoConst.h"
|
#include "CryptoConst.h"
|
||||||
|
@ -293,14 +292,6 @@ namespace data
|
||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateRandomDHKeysPair (DHKeysPair * keys)
|
|
||||||
{
|
|
||||||
if (!keys) return;
|
|
||||||
CryptoPP::AutoSeededRandomPool rnd;
|
|
||||||
CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
|
|
||||||
dh.GenerateKeyPair(rnd, keys->privateKey, keys->publicKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
IdentHash CreateRoutingKey (const IdentHash& ident)
|
IdentHash CreateRoutingKey (const IdentHash& ident)
|
||||||
{
|
{
|
||||||
uint8_t buf[41]; // ident + yyyymmdd
|
uint8_t buf[41]; // ident + yyyymmdd
|
||||||
|
|
18
Identity.h
18
Identity.h
|
@ -67,13 +67,6 @@ namespace data
|
||||||
typedef Tag<32> IdentHash;
|
typedef Tag<32> IdentHash;
|
||||||
|
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
|
|
||||||
struct DHKeysPair // transient keys for transport sessions
|
|
||||||
{
|
|
||||||
uint8_t publicKey[256];
|
|
||||||
uint8_t privateKey[256];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Keys
|
struct Keys
|
||||||
{
|
{
|
||||||
uint8_t privateKey[256];
|
uint8_t privateKey[256];
|
||||||
|
@ -82,7 +75,6 @@ namespace data
|
||||||
uint8_t signingKey[128];
|
uint8_t signingKey[128];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const uint8_t CERTIFICATE_TYPE_NULL = 0;
|
const uint8_t CERTIFICATE_TYPE_NULL = 0;
|
||||||
const uint8_t CERTIFICATE_TYPE_HASHCASH = 1;
|
const uint8_t CERTIFICATE_TYPE_HASHCASH = 1;
|
||||||
const uint8_t CERTIFICATE_TYPE_HIDDEN = 2;
|
const uint8_t CERTIFICATE_TYPE_HIDDEN = 2;
|
||||||
|
@ -105,7 +97,10 @@ namespace data
|
||||||
Identity& operator=(const Keys& keys);
|
Identity& operator=(const Keys& keys);
|
||||||
size_t FromBuffer (const uint8_t * buf, size_t len);
|
size_t FromBuffer (const uint8_t * buf, size_t len);
|
||||||
IdentHash Hash () const;
|
IdentHash Hash () const;
|
||||||
};
|
};
|
||||||
|
#pragma pack()
|
||||||
|
Keys CreateRandomKeys ();
|
||||||
|
|
||||||
const size_t DEFAULT_IDENTITY_SIZE = sizeof (Identity); // 387 bytes
|
const size_t DEFAULT_IDENTITY_SIZE = sizeof (Identity); // 387 bytes
|
||||||
|
|
||||||
const uint16_t CRYPTO_KEY_TYPE_ELGAMAL = 0;
|
const uint16_t CRYPTO_KEY_TYPE_ELGAMAL = 0;
|
||||||
|
@ -183,11 +178,6 @@ namespace data
|
||||||
uint8_t m_SigningPrivateKey[128]; // assume private key doesn't exceed 128 bytes
|
uint8_t m_SigningPrivateKey[128]; // assume private key doesn't exceed 128 bytes
|
||||||
i2p::crypto::Signer * m_Signer;
|
i2p::crypto::Signer * m_Signer;
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack()
|
|
||||||
|
|
||||||
Keys CreateRandomKeys ();
|
|
||||||
void CreateRandomDHKeysPair (DHKeysPair * keys); // for transport sessions
|
|
||||||
|
|
||||||
// kademlia
|
// kademlia
|
||||||
struct XORMetric
|
struct XORMetric
|
||||||
|
|
|
@ -9,7 +9,7 @@ LIBS =
|
||||||
# http://www.hutsby.net/2011/08/macs-with-aes-ni.html
|
# http://www.hutsby.net/2011/08/macs-with-aes-ni.html
|
||||||
# Seems like all recent Mac's have AES-NI, after firmware upgrade 2.2
|
# Seems like all recent Mac's have AES-NI, after firmware upgrade 2.2
|
||||||
# Found no good way to detect it from command line. TODO: Might be some osx sysinfo magic
|
# Found no good way to detect it from command line. TODO: Might be some osx sysinfo magic
|
||||||
CFLAGS += -DAESNI
|
CFLAGS += -maes -DAESNI
|
||||||
|
|
||||||
# Apple Mac OSX
|
# Apple Mac OSX
|
||||||
UNAME_S := $(shell uname -s)
|
UNAME_S := $(shell uname -s)
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
#include "I2PEndian.h"
|
#include "I2PEndian.h"
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include <cryptopp/dh.h>
|
#include <cryptopp/dh.h>
|
||||||
#include <cryptopp/dsa.h>
|
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "Timestamp.h"
|
#include "Timestamp.h"
|
||||||
|
@ -11,28 +10,27 @@
|
||||||
#include "I2NPProtocol.h"
|
#include "I2NPProtocol.h"
|
||||||
#include "RouterContext.h"
|
#include "RouterContext.h"
|
||||||
#include "Transports.h"
|
#include "Transports.h"
|
||||||
|
#include "NetDb.h"
|
||||||
#include "NTCPSession.h"
|
#include "NTCPSession.h"
|
||||||
|
|
||||||
using namespace i2p::crypto;
|
using namespace i2p::crypto;
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace ntcp
|
namespace transport
|
||||||
{
|
{
|
||||||
NTCPSession::NTCPSession (boost::asio::io_service& service, i2p::data::RouterInfo& in_RemoteRouterInfo):
|
NTCPSession::NTCPSession (boost::asio::io_service& service, const i2p::data::RouterInfo * in_RemoteRouter):
|
||||||
m_Socket (service), m_TerminationTimer (service), m_IsEstablished (false),
|
TransportSession (in_RemoteRouter), m_Socket (service),
|
||||||
m_DHKeysPair (nullptr), m_RemoteRouterInfo (in_RemoteRouterInfo),
|
m_TerminationTimer (service), m_IsEstablished (false), m_ReceiveBufferOffset (0),
|
||||||
m_ReceiveBufferOffset (0), m_NextMessage (nullptr),
|
m_NextMessage (nullptr), m_NumSentBytes (0), m_NumReceivedBytes (0)
|
||||||
m_NumSentBytes (0), m_NumReceivedBytes (0)
|
|
||||||
{
|
{
|
||||||
m_DHKeysPair = i2p::transports.GetNextDHKeysPair ();
|
m_DHKeysPair = transports.GetNextDHKeysPair ();
|
||||||
m_Establisher = new Establisher;
|
m_Establisher = new Establisher;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTCPSession::~NTCPSession ()
|
NTCPSession::~NTCPSession ()
|
||||||
{
|
{
|
||||||
delete m_Establisher;
|
delete m_Establisher;
|
||||||
delete m_DHKeysPair;
|
|
||||||
if (m_NextMessage)
|
if (m_NextMessage)
|
||||||
i2p::DeleteI2NPMessage (m_NextMessage);
|
i2p::DeleteI2NPMessage (m_NextMessage);
|
||||||
for (auto it :m_DelayedMessages)
|
for (auto it :m_DelayedMessages)
|
||||||
|
@ -79,12 +77,13 @@ namespace ntcp
|
||||||
{
|
{
|
||||||
m_IsEstablished = false;
|
m_IsEstablished = false;
|
||||||
m_Socket.close ();
|
m_Socket.close ();
|
||||||
i2p::transports.RemoveNTCPSession (this);
|
transports.RemoveNTCPSession (this);
|
||||||
int numDelayed = 0;
|
int numDelayed = 0;
|
||||||
for (auto it :m_DelayedMessages)
|
for (auto it :m_DelayedMessages)
|
||||||
{
|
{
|
||||||
// try to send them again
|
// try to send them again
|
||||||
i2p::transports.SendMessage (m_RemoteRouterInfo.GetIdentHash (), it);
|
if (m_RemoteRouter)
|
||||||
|
transports.SendMessage (m_RemoteRouter->GetIdentHash (), it);
|
||||||
numDelayed++;
|
numDelayed++;
|
||||||
}
|
}
|
||||||
m_DelayedMessages.clear ();
|
m_DelayedMessages.clear ();
|
||||||
|
@ -121,12 +120,12 @@ namespace ntcp
|
||||||
void NTCPSession::ClientLogin ()
|
void NTCPSession::ClientLogin ()
|
||||||
{
|
{
|
||||||
if (!m_DHKeysPair)
|
if (!m_DHKeysPair)
|
||||||
m_DHKeysPair = i2p::transports.GetNextDHKeysPair ();
|
m_DHKeysPair = transports.GetNextDHKeysPair ();
|
||||||
// send Phase1
|
// send Phase1
|
||||||
const uint8_t * x = m_DHKeysPair->publicKey;
|
const uint8_t * x = m_DHKeysPair->publicKey;
|
||||||
memcpy (m_Establisher->phase1.pubKey, x, 256);
|
memcpy (m_Establisher->phase1.pubKey, x, 256);
|
||||||
CryptoPP::SHA256().CalculateDigest(m_Establisher->phase1.HXxorHI, x, 256);
|
CryptoPP::SHA256().CalculateDigest(m_Establisher->phase1.HXxorHI, x, 256);
|
||||||
const uint8_t * ident = m_RemoteRouterInfo.GetIdentHash ();
|
const uint8_t * ident = m_RemoteIdentity.GetIdentHash ();
|
||||||
for (int i = 0; i < 32; i++)
|
for (int i = 0; i < 32; i++)
|
||||||
m_Establisher->phase1.HXxorHI[i] ^= ident[i];
|
m_Establisher->phase1.HXxorHI[i] ^= ident[i];
|
||||||
|
|
||||||
|
@ -191,7 +190,7 @@ namespace ntcp
|
||||||
void NTCPSession::SendPhase2 ()
|
void NTCPSession::SendPhase2 ()
|
||||||
{
|
{
|
||||||
if (!m_DHKeysPair)
|
if (!m_DHKeysPair)
|
||||||
m_DHKeysPair = i2p::transports.GetNextDHKeysPair ();
|
m_DHKeysPair = transports.GetNextDHKeysPair ();
|
||||||
const uint8_t * y = m_DHKeysPair->publicKey;
|
const uint8_t * y = m_DHKeysPair->publicKey;
|
||||||
memcpy (m_Establisher->phase2.pubKey, y, 256);
|
memcpy (m_Establisher->phase2.pubKey, y, 256);
|
||||||
uint8_t xy[512];
|
uint8_t xy[512];
|
||||||
|
@ -239,8 +238,9 @@ namespace ntcp
|
||||||
LogPrint ("Phase 2 read error: ", ecode.message (), ". Wrong ident assumed");
|
LogPrint ("Phase 2 read error: ", ecode.message (), ". Wrong ident assumed");
|
||||||
if (ecode != boost::asio::error::operation_aborted)
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
{
|
{
|
||||||
GetRemoteRouterInfo ().SetUnreachable (true); // this RouterInfo is not valid
|
// this RI is not valid
|
||||||
i2p::transports.ReuseDHKeysPair (m_DHKeysPair);
|
i2p::data::netdb.SetUnreachable (GetRemoteIdentity ().GetIdentHash (), true);
|
||||||
|
transports.ReuseDHKeysPair (m_DHKeysPair);
|
||||||
m_DHKeysPair = nullptr;
|
m_DHKeysPair = nullptr;
|
||||||
Terminate ();
|
Terminate ();
|
||||||
}
|
}
|
||||||
|
@ -265,7 +265,7 @@ namespace ntcp
|
||||||
if (memcmp (hxy, m_Establisher->phase2.encrypted.hxy, 32))
|
if (memcmp (hxy, m_Establisher->phase2.encrypted.hxy, 32))
|
||||||
{
|
{
|
||||||
LogPrint ("Incorrect hash");
|
LogPrint ("Incorrect hash");
|
||||||
i2p::transports.ReuseDHKeysPair (m_DHKeysPair);
|
transports.ReuseDHKeysPair (m_DHKeysPair);
|
||||||
m_DHKeysPair = nullptr;
|
m_DHKeysPair = nullptr;
|
||||||
Terminate ();
|
Terminate ();
|
||||||
return ;
|
return ;
|
||||||
|
@ -277,14 +277,14 @@ namespace ntcp
|
||||||
void NTCPSession::SendPhase3 ()
|
void NTCPSession::SendPhase3 ()
|
||||||
{
|
{
|
||||||
m_Establisher->phase3.size = htons (i2p::data::DEFAULT_IDENTITY_SIZE);
|
m_Establisher->phase3.size = htons (i2p::data::DEFAULT_IDENTITY_SIZE);
|
||||||
memcpy (&m_Establisher->phase3.ident, &i2p::context.GetRouterIdentity (), i2p::data::DEFAULT_IDENTITY_SIZE);
|
memcpy (&m_Establisher->phase3.ident, &i2p::context.GetIdentity ().GetStandardIdentity (), i2p::data::DEFAULT_IDENTITY_SIZE); // TODO:
|
||||||
uint32_t tsA = htobe32 (i2p::util::GetSecondsSinceEpoch ());
|
uint32_t tsA = htobe32 (i2p::util::GetSecondsSinceEpoch ());
|
||||||
m_Establisher->phase3.timestamp = tsA;
|
m_Establisher->phase3.timestamp = tsA;
|
||||||
|
|
||||||
SignedData s;
|
SignedData s;
|
||||||
memcpy (s.x, m_Establisher->phase1.pubKey, 256);
|
memcpy (s.x, m_Establisher->phase1.pubKey, 256);
|
||||||
memcpy (s.y, m_Establisher->phase2.pubKey, 256);
|
memcpy (s.y, m_Establisher->phase2.pubKey, 256);
|
||||||
memcpy (s.ident, m_RemoteRouterInfo.GetIdentHash (), 32);
|
memcpy (s.ident, m_RemoteIdentity.GetIdentHash (), 32);
|
||||||
s.tsA = tsA;
|
s.tsA = tsA;
|
||||||
s.tsB = m_Establisher->phase2.encrypted.timestamp;
|
s.tsB = m_Establisher->phase2.encrypted.timestamp;
|
||||||
i2p::context.Sign ((uint8_t *)&s, sizeof (s), m_Establisher->phase3.signature);
|
i2p::context.Sign ((uint8_t *)&s, sizeof (s), m_Establisher->phase3.signature);
|
||||||
|
@ -324,7 +324,7 @@ namespace ntcp
|
||||||
{
|
{
|
||||||
LogPrint ("Phase 3 received: ", bytes_transferred);
|
LogPrint ("Phase 3 received: ", bytes_transferred);
|
||||||
m_Decryption.Decrypt ((uint8_t *)&m_Establisher->phase3, sizeof(NTCPPhase3), (uint8_t *)&m_Establisher->phase3);
|
m_Decryption.Decrypt ((uint8_t *)&m_Establisher->phase3, sizeof(NTCPPhase3), (uint8_t *)&m_Establisher->phase3);
|
||||||
m_RemoteRouterInfo.SetRouterIdentity (m_Establisher->phase3.ident);
|
m_RemoteIdentity = m_Establisher->phase3.ident;
|
||||||
|
|
||||||
SignedData s;
|
SignedData s;
|
||||||
memcpy (s.x, m_Establisher->phase1.pubKey, 256);
|
memcpy (s.x, m_Establisher->phase1.pubKey, 256);
|
||||||
|
@ -333,10 +333,7 @@ namespace ntcp
|
||||||
s.tsA = m_Establisher->phase3.timestamp;
|
s.tsA = m_Establisher->phase3.timestamp;
|
||||||
s.tsB = tsB;
|
s.tsB = tsB;
|
||||||
|
|
||||||
CryptoPP::DSA::PublicKey pubKey;
|
if (!m_RemoteIdentity.Verify ((uint8_t *)&s, sizeof(s), m_Establisher->phase3.signature))
|
||||||
pubKey.Initialize (dsap, dsaq, dsag, CryptoPP::Integer (m_RemoteRouterInfo.GetRouterIdentity ().signingKey, 128));
|
|
||||||
CryptoPP::DSA::Verifier verifier (pubKey);
|
|
||||||
if (!verifier.VerifyMessage ((uint8_t *)&s, sizeof(s), m_Establisher->phase3.signature, 40))
|
|
||||||
{
|
{
|
||||||
LogPrint ("signature verification failed");
|
LogPrint ("signature verification failed");
|
||||||
Terminate ();
|
Terminate ();
|
||||||
|
@ -352,7 +349,7 @@ namespace ntcp
|
||||||
SignedData s;
|
SignedData s;
|
||||||
memcpy (s.x, m_Establisher->phase1.pubKey, 256);
|
memcpy (s.x, m_Establisher->phase1.pubKey, 256);
|
||||||
memcpy (s.y, m_Establisher->phase2.pubKey, 256);
|
memcpy (s.y, m_Establisher->phase2.pubKey, 256);
|
||||||
memcpy (s.ident, m_RemoteRouterInfo.GetIdentHash (), 32);
|
memcpy (s.ident, m_RemoteIdentity.GetIdentHash (), 32);
|
||||||
s.tsA = m_Establisher->phase3.timestamp;
|
s.tsA = m_Establisher->phase3.timestamp;
|
||||||
s.tsB = tsB;
|
s.tsB = tsB;
|
||||||
i2p::context.Sign ((uint8_t *)&s, sizeof (s), m_Establisher->phase4.signature);
|
i2p::context.Sign ((uint8_t *)&s, sizeof (s), m_Establisher->phase4.signature);
|
||||||
|
@ -387,7 +384,8 @@ namespace ntcp
|
||||||
LogPrint ("Phase 4 read error: ", ecode.message ());
|
LogPrint ("Phase 4 read error: ", ecode.message ());
|
||||||
if (ecode != boost::asio::error::operation_aborted)
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
{
|
{
|
||||||
GetRemoteRouterInfo ().SetUnreachable (true); // this router doesn't like us
|
// this router doesn't like us
|
||||||
|
i2p::data::netdb.SetUnreachable (GetRemoteIdentity ().GetIdentHash (), true);
|
||||||
Terminate ();
|
Terminate ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -404,10 +402,7 @@ namespace ntcp
|
||||||
s.tsA = tsA;
|
s.tsA = tsA;
|
||||||
s.tsB = m_Establisher->phase2.encrypted.timestamp;
|
s.tsB = m_Establisher->phase2.encrypted.timestamp;
|
||||||
|
|
||||||
CryptoPP::DSA::PublicKey pubKey;
|
if (!m_RemoteIdentity.Verify ((uint8_t *)&s, sizeof(s), m_Establisher->phase4.signature))
|
||||||
pubKey.Initialize (dsap, dsaq, dsag, CryptoPP::Integer (m_RemoteRouterInfo.GetRouterIdentity ().signingKey, 128));
|
|
||||||
CryptoPP::DSA::Verifier verifier (pubKey);
|
|
||||||
if (!verifier.VerifyMessage ((uint8_t *)&s, sizeof(s), m_Establisher->phase4.signature, 40))
|
|
||||||
{
|
{
|
||||||
LogPrint ("signature verification failed");
|
LogPrint ("signature verification failed");
|
||||||
Terminate ();
|
Terminate ();
|
||||||
|
@ -601,9 +596,8 @@ namespace ntcp
|
||||||
|
|
||||||
|
|
||||||
NTCPClient::NTCPClient (boost::asio::io_service& service, const boost::asio::ip::address& address,
|
NTCPClient::NTCPClient (boost::asio::io_service& service, const boost::asio::ip::address& address,
|
||||||
int port, i2p::data::RouterInfo& in_RouterInfo):
|
int port, const i2p::data::RouterInfo& in_RouterInfo):
|
||||||
NTCPSession (service, in_RouterInfo),
|
NTCPSession (service, &in_RouterInfo), m_Endpoint (address, port)
|
||||||
m_Endpoint (address, port)
|
|
||||||
{
|
{
|
||||||
Connect ();
|
Connect ();
|
||||||
}
|
}
|
||||||
|
@ -622,13 +616,15 @@ namespace ntcp
|
||||||
LogPrint ("Connect error: ", ecode.message ());
|
LogPrint ("Connect error: ", ecode.message ());
|
||||||
if (ecode != boost::asio::error::operation_aborted)
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
{
|
{
|
||||||
GetRemoteRouterInfo ().SetUnreachable (true);
|
i2p::data::netdb.SetUnreachable (GetRemoteIdentity ().GetIdentHash (), true);
|
||||||
Terminate ();
|
Terminate ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint ("Connected");
|
LogPrint ("Connected");
|
||||||
|
if (GetSocket ().local_endpoint ().protocol () == boost::asio::ip::tcp::v6()) // ipv6
|
||||||
|
context.UpdateV6Address (GetSocket ().local_endpoint ().address ().to_string ());
|
||||||
ClientLogin ();
|
ClientLogin ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -636,11 +632,8 @@ namespace ntcp
|
||||||
void NTCPServerConnection::Connected ()
|
void NTCPServerConnection::Connected ()
|
||||||
{
|
{
|
||||||
LogPrint ("NTCP server session connected");
|
LogPrint ("NTCP server session connected");
|
||||||
SetIsEstablished (true);
|
transports.AddNTCPSession (this);
|
||||||
i2p::transports.AddNTCPSession (this);
|
NTCPSession::Connected ();
|
||||||
|
|
||||||
SendTimeSyncMessage ();
|
|
||||||
SendI2NPMessage (CreateDatabaseStoreMsg ()); // we tell immediately who we are
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,10 +11,11 @@
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
#include "RouterInfo.h"
|
#include "RouterInfo.h"
|
||||||
#include "I2NPProtocol.h"
|
#include "I2NPProtocol.h"
|
||||||
|
#include "TransportSession.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace ntcp
|
namespace transport
|
||||||
{
|
{
|
||||||
|
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
|
@ -65,16 +66,16 @@ namespace ntcp
|
||||||
const size_t NTCP_MAX_MESSAGE_SIZE = 16384;
|
const size_t NTCP_MAX_MESSAGE_SIZE = 16384;
|
||||||
const size_t NTCP_BUFFER_SIZE = 1040; // fits one tunnel message (1028)
|
const size_t NTCP_BUFFER_SIZE = 1040; // fits one tunnel message (1028)
|
||||||
const int NTCP_TERMINATION_TIMEOUT = 120; // 2 minutes
|
const int NTCP_TERMINATION_TIMEOUT = 120; // 2 minutes
|
||||||
class NTCPSession
|
|
||||||
|
class NTCPSession: public TransportSession
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
NTCPSession (boost::asio::io_service& service, i2p::data::RouterInfo& in_RemoteRouterInfo);
|
NTCPSession (boost::asio::io_service& service, const i2p::data::RouterInfo * in_RemoteRouter = nullptr);
|
||||||
virtual ~NTCPSession ();
|
~NTCPSession ();
|
||||||
|
|
||||||
boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; };
|
boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; };
|
||||||
bool IsEstablished () const { return m_IsEstablished; };
|
bool IsEstablished () const { return m_IsEstablished; };
|
||||||
i2p::data::RouterInfo& GetRemoteRouterInfo () { return m_RemoteRouterInfo; };
|
|
||||||
|
|
||||||
void ClientLogin ();
|
void ClientLogin ();
|
||||||
void ServerLogin ();
|
void ServerLogin ();
|
||||||
|
@ -127,13 +128,10 @@ namespace ntcp
|
||||||
boost::asio::ip::tcp::socket m_Socket;
|
boost::asio::ip::tcp::socket m_Socket;
|
||||||
boost::asio::deadline_timer m_TerminationTimer;
|
boost::asio::deadline_timer m_TerminationTimer;
|
||||||
bool m_IsEstablished;
|
bool m_IsEstablished;
|
||||||
i2p::data::DHKeysPair * m_DHKeysPair; // X - for client and Y - for server
|
|
||||||
|
|
||||||
i2p::crypto::CBCDecryption m_Decryption;
|
i2p::crypto::CBCDecryption m_Decryption;
|
||||||
i2p::crypto::CBCEncryption m_Encryption;
|
i2p::crypto::CBCEncryption m_Encryption;
|
||||||
CryptoPP::Adler32 m_Adler;
|
CryptoPP::Adler32 m_Adler;
|
||||||
|
|
||||||
i2p::data::RouterInfo& m_RemoteRouterInfo;
|
|
||||||
|
|
||||||
struct Establisher
|
struct Establisher
|
||||||
{
|
{
|
||||||
|
@ -157,7 +155,7 @@ namespace ntcp
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
NTCPClient (boost::asio::io_service& service, const boost::asio::ip::address& address, int port, i2p::data::RouterInfo& in_RouterInfo);
|
NTCPClient (boost::asio::io_service& service, const boost::asio::ip::address& address, int port, const i2p::data::RouterInfo& in_RouterInfo);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -174,15 +172,11 @@ namespace ntcp
|
||||||
public:
|
public:
|
||||||
|
|
||||||
NTCPServerConnection (boost::asio::io_service& service):
|
NTCPServerConnection (boost::asio::io_service& service):
|
||||||
NTCPSession (service, m_DummyRemoteRouterInfo) {};
|
NTCPSession (service) {};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual void Connected ();
|
virtual void Connected ();
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
i2p::data::RouterInfo m_DummyRemoteRouterInfo;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
17
NetDb.cpp
17
NetDb.cpp
|
@ -15,6 +15,8 @@
|
||||||
#include "Reseed.h"
|
#include "Reseed.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
using namespace i2p::transport;
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace data
|
namespace data
|
||||||
|
@ -227,6 +229,13 @@ namespace data
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetDb::SetUnreachable (const IdentHash& ident, bool unreachable)
|
||||||
|
{
|
||||||
|
auto it = m_RouterInfos.find (ident);
|
||||||
|
if (it != m_RouterInfos.end ())
|
||||||
|
return it->second->SetUnreachable (unreachable);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Move to reseed and/or scheduled tasks. (In java version, scheduler fix this as well as sort RIs.)
|
// TODO: Move to reseed and/or scheduled tasks. (In java version, scheduler fix this as well as sort RIs.)
|
||||||
bool NetDb::CreateNetDb(boost::filesystem::path directory)
|
bool NetDb::CreateNetDb(boost::filesystem::path directory)
|
||||||
{
|
{
|
||||||
|
@ -403,7 +412,7 @@ namespace data
|
||||||
RequestedDestination * dest = CreateRequestedDestination (destination, false, false, pool);
|
RequestedDestination * dest = CreateRequestedDestination (destination, false, false, pool);
|
||||||
auto floodfill = GetClosestFloodfill (destination, dest->GetExcludedPeers ());
|
auto floodfill = GetClosestFloodfill (destination, dest->GetExcludedPeers ());
|
||||||
if (floodfill)
|
if (floodfill)
|
||||||
i2p::transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ()));
|
transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -655,10 +664,10 @@ namespace data
|
||||||
if (outbound)
|
if (outbound)
|
||||||
outbound->SendTunnelDataMsg (buf+32, replyTunnelID, replyMsg);
|
outbound->SendTunnelDataMsg (buf+32, replyTunnelID, replyMsg);
|
||||||
else
|
else
|
||||||
i2p::transports.SendMessage (buf+32, i2p::CreateTunnelGatewayMsg (replyTunnelID, replyMsg));
|
transports.SendMessage (buf+32, i2p::CreateTunnelGatewayMsg (replyTunnelID, replyMsg));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
i2p::transports.SendMessage (buf+32, replyMsg);
|
transports.SendMessage (buf+32, replyMsg);
|
||||||
}
|
}
|
||||||
i2p::DeleteI2NPMessage (msg);
|
i2p::DeleteI2NPMessage (msg);
|
||||||
}
|
}
|
||||||
|
@ -712,7 +721,7 @@ namespace data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
i2p::transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ()));
|
i2p::transport::transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
DeleteRequestedDestination (dest);
|
DeleteRequestedDestination (dest);
|
||||||
|
|
6
NetDb.h
6
NetDb.h
|
@ -15,7 +15,6 @@
|
||||||
#include "LeaseSet.h"
|
#include "LeaseSet.h"
|
||||||
#include "Tunnel.h"
|
#include "Tunnel.h"
|
||||||
#include "TunnelPool.h"
|
#include "TunnelPool.h"
|
||||||
#include "AddressBook.h"
|
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
|
@ -67,7 +66,6 @@ namespace data
|
||||||
void AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, i2p::tunnel::InboundTunnel * from);
|
void AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, i2p::tunnel::InboundTunnel * from);
|
||||||
RouterInfo * FindRouter (const IdentHash& ident) const;
|
RouterInfo * FindRouter (const IdentHash& ident) const;
|
||||||
LeaseSet * FindLeaseSet (const IdentHash& destination) const;
|
LeaseSet * FindLeaseSet (const IdentHash& destination) const;
|
||||||
AddressBook& GetAddressBook () { return m_AddressBook; };// TODO: move AddressBook away from NetDb
|
|
||||||
|
|
||||||
void PublishLeaseSet (const LeaseSet * leaseSet, i2p::tunnel::TunnelPool * pool);
|
void PublishLeaseSet (const LeaseSet * leaseSet, i2p::tunnel::TunnelPool * pool);
|
||||||
void RequestDestination (const IdentHash& destination, bool isLeaseSet = false,
|
void RequestDestination (const IdentHash& destination, bool isLeaseSet = false,
|
||||||
|
@ -80,7 +78,8 @@ namespace data
|
||||||
const RouterInfo * GetRandomRouter () const;
|
const RouterInfo * GetRandomRouter () const;
|
||||||
const RouterInfo * GetRandomRouter (const RouterInfo * compatibleWith) const;
|
const RouterInfo * GetRandomRouter (const RouterInfo * compatibleWith) const;
|
||||||
const RouterInfo * GetHighBandwidthRandomRouter (const RouterInfo * compatibleWith) const;
|
const RouterInfo * GetHighBandwidthRandomRouter (const RouterInfo * compatibleWith) const;
|
||||||
|
void SetUnreachable (const IdentHash& ident, bool unreachable);
|
||||||
|
|
||||||
void PostI2NPMsg (I2NPMessage * msg);
|
void PostI2NPMsg (I2NPMessage * msg);
|
||||||
|
|
||||||
// for web interface
|
// for web interface
|
||||||
|
@ -120,7 +119,6 @@ namespace data
|
||||||
int m_ReseedRetries;
|
int m_ReseedRetries;
|
||||||
std::thread * m_Thread;
|
std::thread * m_Thread;
|
||||||
i2p::util::Queue<I2NPMessage> m_Queue; // of I2NPDatabaseStoreMsg
|
i2p::util::Queue<I2NPMessage> m_Queue; // of I2NPDatabaseStoreMsg
|
||||||
AddressBook m_AddressBook;
|
|
||||||
|
|
||||||
static const char m_NetDbPath[];
|
static const char m_NetDbPath[];
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,10 +35,10 @@ $ ./i2p --host=YOUR_PUBLIC_IP
|
||||||
The client should now reseed by itself.
|
The client should now reseed by itself.
|
||||||
|
|
||||||
To visit an I2P page, you need to find the b32 address of your destination.
|
To visit an I2P page, you need to find the b32 address of your destination.
|
||||||
After that, go to the webconsole and add it behind the url. (Remove http:// and b32.i2p from the address)
|
After that, go to the webconsole and add it behind the url. (Remove http:// from the address)
|
||||||
|
|
||||||
This should resulting in for example:
|
This should resulting in for example:
|
||||||
http://localhost:7070/4oes3rlgrpbkmzv4lqcfili23h3cvpwslqcfjlk6vvguxyggspwa
|
http://localhost:7070/4oes3rlgrpbkmzv4lqcfili23h3cvpwslqcfjlk6vvguxyggspwa.b32.i2p
|
||||||
|
|
||||||
|
|
||||||
Options
|
Options
|
||||||
|
@ -51,6 +51,7 @@ Options
|
||||||
* --daemon= - Enable or disable daemon mode. 1 for yes, 0 for no.
|
* --daemon= - Enable or disable daemon mode. 1 for yes, 0 for no.
|
||||||
* --service= - 1 if uses system folders (/var/run/i2pd.pid, /var/log/i2pd.log, /var/lib/i2pd).
|
* --service= - 1 if uses system folders (/var/run/i2pd.pid, /var/log/i2pd.log, /var/lib/i2pd).
|
||||||
* --unreachable= - 1 if router is declared as unreachable and works through introducers.
|
* --unreachable= - 1 if router is declared as unreachable and works through introducers.
|
||||||
|
* --v6= - 1 if supports communication through ipv6, off by default
|
||||||
* --httpproxyport= - The port to listen on (HTTP Proxy)
|
* --httpproxyport= - The port to listen on (HTTP Proxy)
|
||||||
* --socksproxyport= - The port to listen on (SOCKS Proxy)
|
* --socksproxyport= - The port to listen on (SOCKS Proxy)
|
||||||
* --ircport= - The local port of IRC tunnel to listen on. 6668 by default
|
* --ircport= - The local port of IRC tunnel to listen on. 6668 by default
|
||||||
|
|
|
@ -78,7 +78,7 @@ namespace i2p
|
||||||
auto newAddress = boost::asio::ip::address::from_string (host);
|
auto newAddress = boost::asio::ip::address::from_string (host);
|
||||||
for (auto& address : m_RouterInfo.GetAddresses ())
|
for (auto& address : m_RouterInfo.GetAddresses ())
|
||||||
{
|
{
|
||||||
if (address.host != newAddress)
|
if (address.host != newAddress && address.IsCompatible (newAddress))
|
||||||
{
|
{
|
||||||
address.host = newAddress;
|
address.host = newAddress;
|
||||||
updated = true;
|
updated = true;
|
||||||
|
@ -130,7 +130,45 @@ namespace i2p
|
||||||
// update
|
// update
|
||||||
UpdateRouterInfo ();
|
UpdateRouterInfo ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RouterContext::SetSupportsV6 (bool supportsV6)
|
||||||
|
{
|
||||||
|
if (supportsV6)
|
||||||
|
m_RouterInfo.EnableV6 ();
|
||||||
|
else
|
||||||
|
m_RouterInfo.DisableV6 ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouterContext::UpdateV6Address (const std::string& host)
|
||||||
|
{
|
||||||
|
bool updated = false, found = false;
|
||||||
|
int port = 0;
|
||||||
|
auto newAddress = boost::asio::ip::address::from_string (host);
|
||||||
|
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||||
|
for (auto& addr : addresses)
|
||||||
|
{
|
||||||
|
if (addr.host.is_v6 ())
|
||||||
|
{
|
||||||
|
if (addr.host != newAddress)
|
||||||
|
{
|
||||||
|
addr.host = newAddress;
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
port = addr.port;
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
// create new address
|
||||||
|
m_RouterInfo.AddNTCPAddress (host.c_str (), port);
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
if (updated)
|
||||||
|
UpdateRouterInfo ();
|
||||||
|
}
|
||||||
|
|
||||||
bool RouterContext::Load ()
|
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::ofstream::in);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define ROUTER_CONTEXT_H__
|
#define ROUTER_CONTEXT_H__
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <string>
|
||||||
#include <cryptopp/dsa.h>
|
#include <cryptopp/dsa.h>
|
||||||
#include <cryptopp/osrng.h>
|
#include <cryptopp/osrng.h>
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
|
@ -22,9 +23,6 @@ namespace i2p
|
||||||
void Init ();
|
void Init ();
|
||||||
|
|
||||||
i2p::data::RouterInfo& GetRouterInfo () { return m_RouterInfo; };
|
i2p::data::RouterInfo& GetRouterInfo () { return m_RouterInfo; };
|
||||||
const uint8_t * GetPrivateKey () const { return m_Keys.GetPrivateKey (); };
|
|
||||||
const i2p::data::Identity& GetRouterIdentity () const { return m_RouterInfo.GetRouterIdentity (); };
|
|
||||||
const i2p::data::IdentHash& GetRouterIdentHash () const { return m_RouterInfo.GetIdentHash (); };
|
|
||||||
CryptoPP::RandomNumberGenerator& GetRandomNumberGenerator () { return m_Rnd; };
|
CryptoPP::RandomNumberGenerator& GetRandomNumberGenerator () { return m_Rnd; };
|
||||||
|
|
||||||
void UpdatePort (int port); // called from Daemon
|
void UpdatePort (int port); // called from Daemon
|
||||||
|
@ -35,6 +33,9 @@ namespace i2p
|
||||||
void SetUnreachable ();
|
void SetUnreachable ();
|
||||||
bool AcceptsTunnels () const { return m_AcceptsTunnels; };
|
bool AcceptsTunnels () const { return m_AcceptsTunnels; };
|
||||||
void SetAcceptsTunnels (bool acceptsTunnels) { m_AcceptsTunnels = acceptsTunnels; };
|
void SetAcceptsTunnels (bool acceptsTunnels) { m_AcceptsTunnels = acceptsTunnels; };
|
||||||
|
bool SupportsV6 () const { return m_RouterInfo.IsV6 (); };
|
||||||
|
void SetSupportsV6 (bool supportsV6);
|
||||||
|
void UpdateV6Address (const std::string& host); // called from NTCP session
|
||||||
|
|
||||||
// implements LocalDestination
|
// implements LocalDestination
|
||||||
const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; };
|
const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; };
|
||||||
|
|
|
@ -59,7 +59,6 @@ namespace data
|
||||||
{
|
{
|
||||||
m_RouterIdentity = identity;
|
m_RouterIdentity = identity;
|
||||||
m_IdentHash = m_RouterIdentity.Hash ();
|
m_IdentHash = m_RouterIdentity.Hash ();
|
||||||
UpdateIdentHashBase64 ();
|
|
||||||
m_Timestamp = i2p::util::GetMillisecondsSinceEpoch ();
|
m_Timestamp = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,7 +225,6 @@ namespace data
|
||||||
}
|
}
|
||||||
|
|
||||||
CryptoPP::SHA256().CalculateDigest(m_IdentHash, (uint8_t *)&m_RouterIdentity, sizeof (m_RouterIdentity));
|
CryptoPP::SHA256().CalculateDigest(m_IdentHash, (uint8_t *)&m_RouterIdentity, sizeof (m_RouterIdentity));
|
||||||
UpdateIdentHashBase64 ();
|
|
||||||
|
|
||||||
if (!m_SupportedTransports || !m_Addresses.size() || (UsesIntroducer () && !introducers))
|
if (!m_SupportedTransports || !m_Addresses.size() || (UsesIntroducer () && !introducers))
|
||||||
SetUnreachable (true);
|
SetUnreachable (true);
|
||||||
|
@ -279,18 +277,9 @@ namespace data
|
||||||
|
|
||||||
SetProperty ("caps", caps.c_str ());
|
SetProperty ("caps", caps.c_str ());
|
||||||
}
|
}
|
||||||
|
|
||||||
void RouterInfo::UpdateIdentHashBase64 ()
|
|
||||||
{
|
|
||||||
size_t l = i2p::data::ByteStreamToBase64 (m_IdentHash, 32, m_IdentHashBase64, 48);
|
|
||||||
m_IdentHashBase64[l] = 0;
|
|
||||||
memcpy (m_IdentHashAbbreviation, m_IdentHashBase64, 4);
|
|
||||||
m_IdentHashAbbreviation[4] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RouterInfo::WriteToStream (std::ostream& s)
|
void RouterInfo::WriteToStream (std::ostream& s)
|
||||||
{
|
{
|
||||||
s.write ((char *)&m_RouterIdentity, sizeof (m_RouterIdentity));
|
|
||||||
uint64_t ts = htobe64 (m_Timestamp);
|
uint64_t ts = htobe64 (m_Timestamp);
|
||||||
s.write ((char *)&ts, sizeof (ts));
|
s.write ((char *)&ts, sizeof (ts));
|
||||||
|
|
||||||
|
@ -410,7 +399,7 @@ namespace data
|
||||||
if (!m_Buffer)
|
if (!m_Buffer)
|
||||||
{
|
{
|
||||||
if (LoadFile ())
|
if (LoadFile ())
|
||||||
LogPrint ("Buffer for ", m_IdentHashAbbreviation, " loaded from file");
|
LogPrint ("Buffer for ", GetIdentHashAbbreviation (), " loaded from file");
|
||||||
}
|
}
|
||||||
return m_Buffer;
|
return m_Buffer;
|
||||||
}
|
}
|
||||||
|
@ -419,6 +408,9 @@ namespace data
|
||||||
{
|
{
|
||||||
m_Timestamp = i2p::util::GetMillisecondsSinceEpoch (); // refresh timstamp
|
m_Timestamp = i2p::util::GetMillisecondsSinceEpoch (); // refresh timstamp
|
||||||
std::stringstream s;
|
std::stringstream s;
|
||||||
|
uint8_t ident[1024];
|
||||||
|
auto identLen = privateKeys.GetPublic ().ToBuffer (ident, 1024);
|
||||||
|
s.write ((char *)ident, identLen);
|
||||||
WriteToStream (s);
|
WriteToStream (s);
|
||||||
m_BufferLen = s.str ().size ();
|
m_BufferLen = s.str ().size ();
|
||||||
if (!m_Buffer)
|
if (!m_Buffer)
|
||||||
|
@ -466,7 +458,7 @@ namespace data
|
||||||
addr.cost = 2;
|
addr.cost = 2;
|
||||||
addr.date = 0;
|
addr.date = 0;
|
||||||
m_Addresses.push_back(addr);
|
m_Addresses.push_back(addr);
|
||||||
m_SupportedTransports |= eNTCPV4;
|
m_SupportedTransports |= addr.host.is_v6 () ? eNTCPV6 : eNTCPV4;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RouterInfo::AddSSUAddress (const char * host, int port, const uint8_t * key)
|
void RouterInfo::AddSSUAddress (const char * host, int port, const uint8_t * key)
|
||||||
|
@ -479,7 +471,7 @@ namespace data
|
||||||
addr.date = 0;
|
addr.date = 0;
|
||||||
memcpy (addr.key, key, 32);
|
memcpy (addr.key, key, 32);
|
||||||
m_Addresses.push_back(addr);
|
m_Addresses.push_back(addr);
|
||||||
m_SupportedTransports |= eSSUV4;
|
m_SupportedTransports |= addr.host.is_v6 () ? eNTCPV6 : eSSUV4;
|
||||||
m_Caps |= eSSUTesting;
|
m_Caps |= eSSUTesting;
|
||||||
m_Caps |= eSSUIntroducer;
|
m_Caps |= eSSUIntroducer;
|
||||||
}
|
}
|
||||||
|
@ -568,6 +560,34 @@ namespace data
|
||||||
return m_SupportedTransports & (eSSUV4 | eSSUV6);
|
return m_SupportedTransports & (eSSUV4 | eSSUV6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RouterInfo::IsV6 () const
|
||||||
|
{
|
||||||
|
return m_SupportedTransports & (eNTCPV6 | eSSUV6);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouterInfo::EnableV6 ()
|
||||||
|
{
|
||||||
|
if (!IsV6 ())
|
||||||
|
m_SupportedTransports |= eNTCPV6;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouterInfo::DisableV6 ()
|
||||||
|
{
|
||||||
|
if (IsV6 ())
|
||||||
|
{
|
||||||
|
m_SupportedTransports &= ~eNTCPV6;
|
||||||
|
for (size_t i = 0; i < m_Addresses.size (); i++)
|
||||||
|
{
|
||||||
|
if (m_Addresses[i].transportStyle == i2p::data::RouterInfo::eTransportNTCP &&
|
||||||
|
m_Addresses[i].host.is_v6 ())
|
||||||
|
{
|
||||||
|
m_Addresses.erase (m_Addresses.begin () + i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool RouterInfo::UsesIntroducer () const
|
bool RouterInfo::UsesIntroducer () const
|
||||||
{
|
{
|
||||||
return m_Caps & Caps::eUnreachable; // non-reachable
|
return m_Caps & Caps::eUnreachable; // non-reachable
|
||||||
|
|
17
RouterInfo.h
17
RouterInfo.h
|
@ -75,10 +75,16 @@ namespace data
|
||||||
// SSU only
|
// SSU only
|
||||||
Tag<32> key; // intro key for SSU
|
Tag<32> key; // intro key for SSU
|
||||||
std::vector<Introducer> introducers;
|
std::vector<Introducer> introducers;
|
||||||
|
|
||||||
|
bool IsCompatible (const boost::asio::ip::address& other) const
|
||||||
|
{
|
||||||
|
return (host.is_v4 () && other.is_v4 ()) ||
|
||||||
|
(host.is_v6 () && other.is_v6 ());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
RouterInfo (const std::string& fullPath);
|
RouterInfo (const std::string& fullPath);
|
||||||
RouterInfo (): m_Buffer (nullptr) { m_IdentHashBase64[0] = 0; m_IdentHashAbbreviation[0] = 0; };
|
RouterInfo (): m_Buffer (nullptr) { };
|
||||||
RouterInfo (const RouterInfo& ) = default;
|
RouterInfo (const RouterInfo& ) = default;
|
||||||
RouterInfo& operator=(const RouterInfo& ) = default;
|
RouterInfo& operator=(const RouterInfo& ) = default;
|
||||||
RouterInfo (const uint8_t * buf, int len);
|
RouterInfo (const uint8_t * buf, int len);
|
||||||
|
@ -86,8 +92,8 @@ namespace data
|
||||||
|
|
||||||
const Identity& GetRouterIdentity () const { return m_RouterIdentity; };
|
const Identity& GetRouterIdentity () const { return m_RouterIdentity; };
|
||||||
void SetRouterIdentity (const Identity& identity);
|
void SetRouterIdentity (const Identity& identity);
|
||||||
const char * GetIdentHashBase64 () const { return m_IdentHashBase64; };
|
std::string GetIdentHashBase64 () const { return m_IdentHash.ToBase64 (); };
|
||||||
const char * GetIdentHashAbbreviation () const { return m_IdentHashAbbreviation; };
|
std::string GetIdentHashAbbreviation () const { return m_IdentHash.ToBase64 ().substr (0, 4); };
|
||||||
uint64_t GetTimestamp () const { return m_Timestamp; };
|
uint64_t GetTimestamp () const { return m_Timestamp; };
|
||||||
std::vector<Address>& GetAddresses () { return m_Addresses; };
|
std::vector<Address>& GetAddresses () { return m_Addresses; };
|
||||||
const Address * GetNTCPAddress (bool v4only = true) const;
|
const Address * GetNTCPAddress (bool v4only = true) const;
|
||||||
|
@ -102,6 +108,9 @@ namespace data
|
||||||
bool IsFloodfill () const;
|
bool IsFloodfill () const;
|
||||||
bool IsNTCP (bool v4only = true) const;
|
bool IsNTCP (bool v4only = true) const;
|
||||||
bool IsSSU (bool v4only = true) const;
|
bool IsSSU (bool v4only = true) const;
|
||||||
|
bool IsV6 () const;
|
||||||
|
void EnableV6 ();
|
||||||
|
void DisableV6 ();
|
||||||
bool IsCompatible (const RouterInfo& other) const { return m_SupportedTransports & other.m_SupportedTransports; };
|
bool IsCompatible (const RouterInfo& other) const { return m_SupportedTransports & other.m_SupportedTransports; };
|
||||||
bool UsesIntroducer () const;
|
bool UsesIntroducer () const;
|
||||||
bool IsIntroducer () const { return m_Caps & eSSUIntroducer; };
|
bool IsIntroducer () const { return m_Caps & eSSUIntroducer; };
|
||||||
|
@ -143,7 +152,6 @@ namespace data
|
||||||
size_t ReadString (char * str, std::istream& s);
|
size_t ReadString (char * str, std::istream& s);
|
||||||
void WriteString (const std::string& str, std::ostream& s);
|
void WriteString (const std::string& str, std::ostream& s);
|
||||||
void ExtractCaps (const char * value);
|
void ExtractCaps (const char * value);
|
||||||
void UpdateIdentHashBase64 ();
|
|
||||||
const Address * GetAddress (TransportStyle s, bool v4only) const;
|
const Address * GetAddress (TransportStyle s, bool v4only) const;
|
||||||
void UpdateCapsProperty ();
|
void UpdateCapsProperty ();
|
||||||
|
|
||||||
|
@ -152,7 +160,6 @@ namespace data
|
||||||
std::string m_FullPath;
|
std::string m_FullPath;
|
||||||
Identity m_RouterIdentity;
|
Identity m_RouterIdentity;
|
||||||
IdentHash m_IdentHash;
|
IdentHash m_IdentHash;
|
||||||
char m_IdentHashBase64[48], m_IdentHashAbbreviation[5];
|
|
||||||
uint8_t * m_Buffer;
|
uint8_t * m_Buffer;
|
||||||
int m_BufferLen;
|
int m_BufferLen;
|
||||||
uint64_t m_Timestamp;
|
uint64_t m_Timestamp;
|
||||||
|
|
99
SAM.cpp
99
SAM.cpp
|
@ -28,8 +28,8 @@ namespace client
|
||||||
if (m_Stream)
|
if (m_Stream)
|
||||||
{
|
{
|
||||||
m_Stream->Close ();
|
m_Stream->Close ();
|
||||||
if (m_Session && m_Session->localDestination)
|
i2p::stream::DeleteStream (m_Stream);
|
||||||
m_Session->localDestination->DeleteStream (m_Stream);
|
m_Stream = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,8 +38,7 @@ namespace client
|
||||||
if (m_Stream)
|
if (m_Stream)
|
||||||
{
|
{
|
||||||
m_Stream->Close ();
|
m_Stream->Close ();
|
||||||
if (m_Session && m_Session->localDestination)
|
i2p::stream::DeleteStream (m_Stream);
|
||||||
m_Session->localDestination->DeleteStream (m_Stream);
|
|
||||||
m_Stream = nullptr;
|
m_Stream = nullptr;
|
||||||
}
|
}
|
||||||
switch (m_SocketType)
|
switch (m_SocketType)
|
||||||
|
@ -58,7 +57,7 @@ namespace client
|
||||||
if (m_Session)
|
if (m_Session)
|
||||||
{
|
{
|
||||||
m_Session->sockets.remove (this);
|
m_Session->sockets.remove (this);
|
||||||
m_Session->localDestination->ResetAcceptor ();
|
m_Session->localDestination->StopAcceptingStreams ();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -210,6 +209,7 @@ namespace client
|
||||||
LogPrint ("SAM session create: ", buf);
|
LogPrint ("SAM session create: ", buf);
|
||||||
std::map<std::string, std::string> params;
|
std::map<std::string, std::string> params;
|
||||||
ExtractParams (buf, len, params);
|
ExtractParams (buf, len, params);
|
||||||
|
std::string& style = params[SAM_PARAM_STYLE];
|
||||||
std::string& id = params[SAM_PARAM_ID];
|
std::string& id = params[SAM_PARAM_ID];
|
||||||
std::string& destination = params[SAM_PARAM_DESTINATION];
|
std::string& destination = params[SAM_PARAM_DESTINATION];
|
||||||
m_ID = id;
|
m_ID = id;
|
||||||
|
@ -224,7 +224,11 @@ namespace client
|
||||||
{
|
{
|
||||||
m_SocketType = eSAMSocketTypeSession;
|
m_SocketType = eSAMSocketTypeSession;
|
||||||
if (m_Session->localDestination->IsReady ())
|
if (m_Session->localDestination->IsReady ())
|
||||||
|
{
|
||||||
|
if (style == SAM_VALUE_DATAGRAM)
|
||||||
|
m_Session->localDestination->CreateDatagramDestination ();
|
||||||
SendSessionCreateReplyOk ();
|
SendSessionCreateReplyOk ();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_Timer.expires_from_now (boost::posix_time::seconds(SAM_SESSION_READINESS_CHECK_INTERVAL));
|
m_Timer.expires_from_now (boost::posix_time::seconds(SAM_SESSION_READINESS_CHECK_INTERVAL));
|
||||||
|
@ -260,7 +264,7 @@ namespace client
|
||||||
priv[l1] = 0;
|
priv[l1] = 0;
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
size_t l2 = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv);
|
size_t l2 = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv);
|
||||||
#else
|
#else
|
||||||
size_t l2 = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv);
|
size_t l2 = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv);
|
||||||
#endif
|
#endif
|
||||||
SendMessageReply (m_Buffer, l2, false);
|
SendMessageReply (m_Buffer, l2, false);
|
||||||
|
@ -302,7 +306,7 @@ namespace client
|
||||||
{
|
{
|
||||||
m_SocketType = eSAMSocketTypeStream;
|
m_SocketType = eSAMSocketTypeStream;
|
||||||
m_Session->sockets.push_back (this);
|
m_Session->sockets.push_back (this);
|
||||||
m_Stream = m_Session->localDestination->CreateNewOutgoingStream (remote);
|
m_Stream = m_Session->localDestination->CreateStream (remote);
|
||||||
m_Stream->Send ((uint8_t *)m_Buffer, 0); // connect
|
m_Stream->Send ((uint8_t *)m_Buffer, 0); // connect
|
||||||
I2PReceive ();
|
I2PReceive ();
|
||||||
SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false);
|
SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false);
|
||||||
|
@ -355,11 +359,11 @@ namespace client
|
||||||
m_Session = m_Owner.FindSession (id);
|
m_Session = m_Owner.FindSession (id);
|
||||||
if (m_Session)
|
if (m_Session)
|
||||||
{
|
{
|
||||||
if (!m_Session->localDestination->IsAcceptorSet ())
|
if (!m_Session->localDestination->IsAcceptingStreams ())
|
||||||
{
|
{
|
||||||
m_SocketType = eSAMSocketTypeAcceptor;
|
m_SocketType = eSAMSocketTypeAcceptor;
|
||||||
m_Session->sockets.push_back (this);
|
m_Session->sockets.push_back (this);
|
||||||
m_Session->localDestination->SetAcceptor (std::bind (&SAMSocket::HandleI2PAccept, this, std::placeholders::_1));
|
m_Session->localDestination->AcceptStreams (std::bind (&SAMSocket::HandleI2PAccept, this, std::placeholders::_1));
|
||||||
SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false);
|
SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -385,8 +389,8 @@ namespace client
|
||||||
l1 = i2p::data::ByteStreamToBase64 (buf, l, pub, 1024);
|
l1 = i2p::data::ByteStreamToBase64 (buf, l, pub, 1024);
|
||||||
pub[l1] = 0;
|
pub[l1] = 0;
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY, pub, priv);
|
size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY, pub, priv);
|
||||||
#else
|
#else
|
||||||
size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY, pub, priv);
|
size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY, pub, priv);
|
||||||
#endif
|
#endif
|
||||||
SendMessageReply (m_Buffer, len, true);
|
SendMessageReply (m_Buffer, len, true);
|
||||||
|
@ -404,7 +408,7 @@ namespace client
|
||||||
i2p::data::IdentHash ident;
|
i2p::data::IdentHash ident;
|
||||||
if (name == "ME")
|
if (name == "ME")
|
||||||
SendNamingLookupReply (nullptr);
|
SendNamingLookupReply (nullptr);
|
||||||
else if (m_Session && i2p::data::netdb.GetAddressBook ().GetIdentHash (name, ident))
|
else if (m_Session && context.GetAddressBook ().GetIdentHash (name, ident))
|
||||||
{
|
{
|
||||||
auto leaseSet = m_Session->localDestination->FindLeaseSet (ident);
|
auto leaseSet = m_Session->localDestination->FindLeaseSet (ident);
|
||||||
if (leaseSet)
|
if (leaseSet)
|
||||||
|
@ -421,7 +425,7 @@ namespace client
|
||||||
{
|
{
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str());
|
size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str());
|
||||||
#else
|
#else
|
||||||
size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str());
|
size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str());
|
||||||
#endif
|
#endif
|
||||||
SendMessageReply (m_Buffer, len, false);
|
SendMessageReply (m_Buffer, len, false);
|
||||||
|
@ -437,8 +441,8 @@ namespace client
|
||||||
size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, pub, 1024);
|
size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, pub, 1024);
|
||||||
pub[l1] = 0;
|
pub[l1] = 0;
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
size_t l2 = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY, pub);
|
size_t l2 = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY, pub);
|
||||||
#else
|
#else
|
||||||
size_t l2 = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY, pub);
|
size_t l2 = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY, pub);
|
||||||
#endif
|
#endif
|
||||||
SendMessageReply (m_Buffer, l2, false);
|
SendMessageReply (m_Buffer, l2, false);
|
||||||
|
@ -530,7 +534,7 @@ namespace client
|
||||||
m_Stream = stream;
|
m_Stream = stream;
|
||||||
auto session = m_Owner.FindSession (m_ID);
|
auto session = m_Owner.FindSession (m_ID);
|
||||||
if (session)
|
if (session)
|
||||||
session->localDestination->ResetAcceptor ();
|
session->localDestination->StopAcceptingStreams ();
|
||||||
if (!m_IsSilent)
|
if (!m_IsSilent)
|
||||||
{
|
{
|
||||||
// send remote peer address
|
// send remote peer address
|
||||||
|
@ -547,7 +551,8 @@ namespace client
|
||||||
SAMBridge::SAMBridge (int port):
|
SAMBridge::SAMBridge (int port):
|
||||||
m_IsRunning (false), m_Thread (nullptr),
|
m_IsRunning (false), m_Thread (nullptr),
|
||||||
m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)),
|
m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)),
|
||||||
m_NewSocket (nullptr)
|
m_DatagramEndpoint (boost::asio::ip::udp::v4 (), port-1), m_DatagramSocket (m_Service, m_DatagramEndpoint),
|
||||||
|
m_NewSocket (nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -560,6 +565,7 @@ namespace client
|
||||||
void SAMBridge::Start ()
|
void SAMBridge::Start ()
|
||||||
{
|
{
|
||||||
Accept ();
|
Accept ();
|
||||||
|
ReceiveDatagram ();
|
||||||
m_IsRunning = true;
|
m_IsRunning = true;
|
||||||
m_Thread = new std::thread (std::bind (&SAMBridge::Run, this));
|
m_Thread = new std::thread (std::bind (&SAMBridge::Run, this));
|
||||||
}
|
}
|
||||||
|
@ -618,7 +624,7 @@ namespace client
|
||||||
|
|
||||||
SAMSession * SAMBridge::CreateSession (const std::string& id, const std::string& destination)
|
SAMSession * SAMBridge::CreateSession (const std::string& id, const std::string& destination)
|
||||||
{
|
{
|
||||||
i2p::stream::StreamingDestination * localDestination = nullptr;
|
ClientDestination * localDestination = nullptr;
|
||||||
if (destination != "")
|
if (destination != "")
|
||||||
{
|
{
|
||||||
uint8_t * buf = new uint8_t[destination.length ()];
|
uint8_t * buf = new uint8_t[destination.length ()];
|
||||||
|
@ -665,5 +671,62 @@ namespace client
|
||||||
return &it->second;
|
return &it->second;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SAMBridge::ReceiveDatagram ()
|
||||||
|
{
|
||||||
|
m_DatagramSocket.async_receive_from (
|
||||||
|
boost::asio::buffer (m_DatagramReceiveBuffer, i2p::datagram::MAX_DATAGRAM_SIZE),
|
||||||
|
m_SenderEndpoint,
|
||||||
|
boost::bind (&SAMBridge::HandleReceivedDatagram, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SAMBridge::HandleReceivedDatagram (const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
||||||
|
{
|
||||||
|
if (!ecode)
|
||||||
|
{
|
||||||
|
m_DatagramReceiveBuffer[bytes_transferred] = 0;
|
||||||
|
char * eol = strchr ((char *)m_DatagramReceiveBuffer, '\n');
|
||||||
|
*eol = 0; eol++;
|
||||||
|
size_t payloadLen = bytes_transferred - ((uint8_t *)eol - m_DatagramReceiveBuffer);
|
||||||
|
LogPrint ("SAM datagram received ", m_DatagramReceiveBuffer," size=", payloadLen);
|
||||||
|
char * sessionID = strchr ((char *)m_DatagramReceiveBuffer, ' ');
|
||||||
|
if (sessionID)
|
||||||
|
{
|
||||||
|
sessionID++;
|
||||||
|
char * destination = strchr (sessionID, ' ');
|
||||||
|
if (destination)
|
||||||
|
{
|
||||||
|
*destination = 0; destination++;
|
||||||
|
auto session = FindSession (sessionID);
|
||||||
|
if (session)
|
||||||
|
{
|
||||||
|
uint8_t ident[1024];
|
||||||
|
size_t l = i2p::data::Base64ToByteStream (destination, strlen(destination), ident, 1024);
|
||||||
|
i2p::data::IdentityEx dest;
|
||||||
|
dest.FromBuffer (ident, l);
|
||||||
|
auto leaseSet = i2p::data::netdb.FindLeaseSet (dest.GetIdentHash ());
|
||||||
|
if (leaseSet)
|
||||||
|
session->localDestination->GetDatagramDestination ()->
|
||||||
|
SendDatagramTo ((uint8_t *)eol, payloadLen, *leaseSet);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrint ("SAM datagram destination not found");
|
||||||
|
i2p::data::netdb.RequestDestination (dest.GetIdentHash (), true,
|
||||||
|
session->localDestination->GetTunnelPool ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint ("Session ", sessionID, " not found");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint ("Missing destination key");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint ("Missing sessionID");
|
||||||
|
ReceiveDatagram ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint ("SAM datagram receive error: ", ecode.message ());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
12
SAM.h
12
SAM.h
|
@ -11,6 +11,7 @@
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
#include "LeaseSet.h"
|
#include "LeaseSet.h"
|
||||||
#include "Streaming.h"
|
#include "Streaming.h"
|
||||||
|
#include "Destination.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
|
@ -46,6 +47,9 @@ namespace client
|
||||||
const char SAM_PARAM_DESTINATION[] = "DESTINATION";
|
const char SAM_PARAM_DESTINATION[] = "DESTINATION";
|
||||||
const char SAM_PARAM_NAME[] = "NAME";
|
const char SAM_PARAM_NAME[] = "NAME";
|
||||||
const char SAM_VALUE_TRANSIENT[] = "TRANSIENT";
|
const char SAM_VALUE_TRANSIENT[] = "TRANSIENT";
|
||||||
|
const char SAM_VALUE_STREAM[] = "STREAM";
|
||||||
|
const char SAM_VALUE_DATAGRAM[] = "DATAGRAM";
|
||||||
|
const char SAM_VALUE_RAW[] = "RAW";
|
||||||
const char SAM_VALUE_TRUE[] = "true";
|
const char SAM_VALUE_TRUE[] = "true";
|
||||||
const char SAM_VALUE_FALSE[] = "false";
|
const char SAM_VALUE_FALSE[] = "false";
|
||||||
|
|
||||||
|
@ -115,7 +119,7 @@ namespace client
|
||||||
|
|
||||||
struct SAMSession
|
struct SAMSession
|
||||||
{
|
{
|
||||||
i2p::stream::StreamingDestination * localDestination;
|
ClientDestination * localDestination;
|
||||||
std::list<SAMSocket *> sockets;
|
std::list<SAMSocket *> sockets;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -141,15 +145,21 @@ namespace client
|
||||||
void Accept ();
|
void Accept ();
|
||||||
void HandleAccept(const boost::system::error_code& ecode);
|
void HandleAccept(const boost::system::error_code& ecode);
|
||||||
|
|
||||||
|
void ReceiveDatagram ();
|
||||||
|
void HandleReceivedDatagram (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool m_IsRunning;
|
bool m_IsRunning;
|
||||||
std::thread * m_Thread;
|
std::thread * m_Thread;
|
||||||
boost::asio::io_service m_Service;
|
boost::asio::io_service m_Service;
|
||||||
boost::asio::ip::tcp::acceptor m_Acceptor;
|
boost::asio::ip::tcp::acceptor m_Acceptor;
|
||||||
|
boost::asio::ip::udp::endpoint m_DatagramEndpoint, m_SenderEndpoint;
|
||||||
|
boost::asio::ip::udp::socket m_DatagramSocket;
|
||||||
SAMSocket * m_NewSocket;
|
SAMSocket * m_NewSocket;
|
||||||
std::mutex m_SessionsMutex;
|
std::mutex m_SessionsMutex;
|
||||||
std::map<std::string, SAMSession> m_Sessions;
|
std::map<std::string, SAMSession> m_Sessions;
|
||||||
|
uint8_t m_DatagramReceiveBuffer[i2p::datagram::MAX_DATAGRAM_SIZE+1];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -224,7 +224,7 @@ namespace proxy
|
||||||
void SOCKS4AHandler::SentConnectionSuccess(const boost::system::error_code & ecode)
|
void SOCKS4AHandler::SentConnectionSuccess(const boost::system::error_code & ecode)
|
||||||
{
|
{
|
||||||
LogPrint("--- socks4a making connection");
|
LogPrint("--- socks4a making connection");
|
||||||
m_stream = i2p::client::context.GetSharedLocalDestination ()->CreateNewOutgoingStream(*m_ls);
|
m_stream = i2p::client::context.GetSharedLocalDestination ()->CreateStream(*m_ls);
|
||||||
m_state = OKAY;
|
m_state = OKAY;
|
||||||
LogPrint("--- socks4a state is ", m_state);
|
LogPrint("--- socks4a state is ", m_state);
|
||||||
AsyncSockRead();
|
AsyncSockRead();
|
||||||
|
|
42
SSU.cpp
42
SSU.cpp
|
@ -12,13 +12,13 @@
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace ssu
|
namespace transport
|
||||||
{
|
{
|
||||||
|
|
||||||
SSUSession::SSUSession (SSUServer& server, boost::asio::ip::udp::endpoint& remoteEndpoint,
|
SSUSession::SSUSession (SSUServer& server, boost::asio::ip::udp::endpoint& remoteEndpoint,
|
||||||
const i2p::data::RouterInfo * router, bool peerTest ):
|
const i2p::data::RouterInfo * router, bool peerTest ): TransportSession (router),
|
||||||
m_Server (server), m_RemoteEndpoint (remoteEndpoint), m_RemoteRouter (router),
|
m_Server (server), m_RemoteEndpoint (remoteEndpoint),
|
||||||
m_Timer (m_Server.GetService ()), m_DHKeysPair (nullptr), m_PeerTest (peerTest),
|
m_Timer (m_Server.GetService ()), m_PeerTest (peerTest),
|
||||||
m_State (eSessionStateUnknown), m_IsSessionKey (false), m_RelayTag (0),
|
m_State (eSessionStateUnknown), m_IsSessionKey (false), m_RelayTag (0),
|
||||||
m_Data (*this), m_NumSentBytes (0), m_NumReceivedBytes (0)
|
m_Data (*this), m_NumSentBytes (0), m_NumReceivedBytes (0)
|
||||||
{
|
{
|
||||||
|
@ -28,8 +28,7 @@ namespace ssu
|
||||||
}
|
}
|
||||||
|
|
||||||
SSUSession::~SSUSession ()
|
SSUSession::~SSUSession ()
|
||||||
{
|
{
|
||||||
delete m_DHKeysPair;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSUSession::CreateAESandMacKey (const uint8_t * pubKey)
|
void SSUSession::CreateAESandMacKey (const uint8_t * pubKey)
|
||||||
|
@ -174,7 +173,7 @@ namespace ssu
|
||||||
LogPrint ("Session request received");
|
LogPrint ("Session request received");
|
||||||
m_RemoteEndpoint = senderEndpoint;
|
m_RemoteEndpoint = senderEndpoint;
|
||||||
if (!m_DHKeysPair)
|
if (!m_DHKeysPair)
|
||||||
m_DHKeysPair = i2p::transports.GetNextDHKeysPair ();
|
m_DHKeysPair = transports.GetNextDHKeysPair ();
|
||||||
CreateAESandMacKey (buf + sizeof (SSUHeader));
|
CreateAESandMacKey (buf + sizeof (SSUHeader));
|
||||||
SendSessionCreated (buf + sizeof (SSUHeader));
|
SendSessionCreated (buf + sizeof (SSUHeader));
|
||||||
}
|
}
|
||||||
|
@ -215,10 +214,7 @@ namespace ssu
|
||||||
m_SessionKeyDecryption.SetIV (((SSUHeader *)buf)->iv);
|
m_SessionKeyDecryption.SetIV (((SSUHeader *)buf)->iv);
|
||||||
m_SessionKeyDecryption.Decrypt (payload, 48, payload);
|
m_SessionKeyDecryption.Decrypt (payload, 48, payload);
|
||||||
// verify
|
// verify
|
||||||
CryptoPP::DSA::PublicKey pubKey;
|
if (!m_RemoteIdentity.Verify (signedData, 532, payload))
|
||||||
pubKey.Initialize (i2p::crypto::dsap, i2p::crypto::dsaq, i2p::crypto::dsag, CryptoPP::Integer (m_RemoteRouter->GetRouterIdentity ().signingKey, 128));
|
|
||||||
CryptoPP::DSA::Verifier verifier (pubKey);
|
|
||||||
if (!verifier.VerifyMessage (signedData, 532, payload, 40))
|
|
||||||
LogPrint ("SSU signature verification failed");
|
LogPrint ("SSU signature verification failed");
|
||||||
|
|
||||||
SendSessionConfirmed (y, ourAddress);
|
SendSessionConfirmed (y, ourAddress);
|
||||||
|
@ -231,17 +227,15 @@ namespace ssu
|
||||||
payload++; // identity fragment info
|
payload++; // identity fragment info
|
||||||
uint16_t identitySize = be16toh (*(uint16_t *)payload);
|
uint16_t identitySize = be16toh (*(uint16_t *)payload);
|
||||||
payload += 2; // size of identity fragment
|
payload += 2; // size of identity fragment
|
||||||
if (identitySize == i2p::data::DEFAULT_IDENTITY_SIZE)
|
m_RemoteIdentity.FromBuffer (payload, identitySize);
|
||||||
{
|
m_Data.UpdatePacketSize (m_RemoteIdentity.GetIdentHash ());
|
||||||
i2p::data::Identity ident;
|
|
||||||
ident.FromBuffer (payload, identitySize);
|
|
||||||
m_RemoteIdent = ident.Hash ();
|
|
||||||
m_Data.UpdatePacketSize (m_RemoteIdent);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LogPrint ("SSU unexpected identity size ", identitySize);
|
|
||||||
payload += identitySize; // identity
|
payload += identitySize; // identity
|
||||||
// TODO: verify signature
|
payload += 4; // signed-on time
|
||||||
|
size_t paddingSize = (payload - buf) + m_RemoteIdentity.GetSignatureLen ();
|
||||||
|
paddingSize >>= 4; // %16
|
||||||
|
if (paddingSize > 0) paddingSize = 16 - paddingSize;
|
||||||
|
payload += paddingSize;
|
||||||
|
// TODO: verify signature (need data from session request), payload points to signature
|
||||||
SendI2NPMessage (CreateDeliveryStatusMsg (0));
|
SendI2NPMessage (CreateDeliveryStatusMsg (0));
|
||||||
Established ();
|
Established ();
|
||||||
}
|
}
|
||||||
|
@ -360,10 +354,10 @@ namespace ssu
|
||||||
uint8_t * payload = buf + sizeof (SSUHeader);
|
uint8_t * payload = buf + sizeof (SSUHeader);
|
||||||
*payload = 1; // 1 fragment
|
*payload = 1; // 1 fragment
|
||||||
payload++; // info
|
payload++; // info
|
||||||
size_t identLen = sizeof (i2p::context.GetRouterIdentity ()); // 387 bytes
|
size_t identLen = i2p::data::DEFAULT_IDENTITY_SIZE; // 387 bytes
|
||||||
*(uint16_t *)(payload) = htobe16 (identLen);
|
*(uint16_t *)(payload) = htobe16 (identLen);
|
||||||
payload += 2; // cursize
|
payload += 2; // cursize
|
||||||
memcpy (payload, (uint8_t *)&i2p::context.GetRouterIdentity (), identLen);
|
memcpy (payload, (uint8_t *)&i2p::context.GetIdentity ().GetStandardIdentity (), identLen); // TODO
|
||||||
payload += identLen;
|
payload += identLen;
|
||||||
uint32_t signedOnTime = i2p::util::GetSecondsSinceEpoch ();
|
uint32_t signedOnTime = i2p::util::GetSecondsSinceEpoch ();
|
||||||
*(uint32_t *)(payload) = htobe32 (signedOnTime); // signed on time
|
*(uint32_t *)(payload) = htobe32 (signedOnTime); // signed on time
|
||||||
|
@ -609,7 +603,7 @@ namespace ssu
|
||||||
{
|
{
|
||||||
// set connect timer
|
// set connect timer
|
||||||
ScheduleConnectTimer ();
|
ScheduleConnectTimer ();
|
||||||
m_DHKeysPair = i2p::transports.GetNextDHKeysPair ();
|
m_DHKeysPair = transports.GetNextDHKeysPair ();
|
||||||
SendSessionRequest ();
|
SendSessionRequest ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
9
SSU.h
9
SSU.h
|
@ -13,11 +13,12 @@
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
#include "RouterInfo.h"
|
#include "RouterInfo.h"
|
||||||
#include "I2NPProtocol.h"
|
#include "I2NPProtocol.h"
|
||||||
|
#include "TransportSession.h"
|
||||||
#include "SSUData.h"
|
#include "SSUData.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace ssu
|
namespace transport
|
||||||
{
|
{
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
struct SSUHeader
|
struct SSUHeader
|
||||||
|
@ -57,7 +58,7 @@ namespace ssu
|
||||||
};
|
};
|
||||||
|
|
||||||
class SSUServer;
|
class SSUServer;
|
||||||
class SSUSession
|
class SSUSession: public TransportSession
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -71,7 +72,6 @@ namespace ssu
|
||||||
void WaitForIntroduction ();
|
void WaitForIntroduction ();
|
||||||
void Close ();
|
void Close ();
|
||||||
boost::asio::ip::udp::endpoint& GetRemoteEndpoint () { return m_RemoteEndpoint; };
|
boost::asio::ip::udp::endpoint& GetRemoteEndpoint () { return m_RemoteEndpoint; };
|
||||||
const i2p::data::RouterInfo * GetRemoteRouter () const { return m_RemoteRouter; };
|
|
||||||
void SendI2NPMessage (I2NPMessage * msg);
|
void SendI2NPMessage (I2NPMessage * msg);
|
||||||
void SendPeerTest (); // Alice
|
void SendPeerTest (); // Alice
|
||||||
|
|
||||||
|
@ -128,10 +128,7 @@ namespace ssu
|
||||||
friend class SSUData; // TODO: change in later
|
friend class SSUData; // TODO: change in later
|
||||||
SSUServer& m_Server;
|
SSUServer& m_Server;
|
||||||
boost::asio::ip::udp::endpoint m_RemoteEndpoint;
|
boost::asio::ip::udp::endpoint m_RemoteEndpoint;
|
||||||
const i2p::data::RouterInfo * m_RemoteRouter;
|
|
||||||
i2p::data::IdentHash m_RemoteIdent; // if m_RemoteRouter is null
|
|
||||||
boost::asio::deadline_timer m_Timer;
|
boost::asio::deadline_timer m_Timer;
|
||||||
i2p::data::DHKeysPair * m_DHKeysPair; // X - for client and Y - for server
|
|
||||||
bool m_PeerTest;
|
bool m_PeerTest;
|
||||||
SessionState m_State;
|
SessionState m_State;
|
||||||
bool m_IsSessionKey;
|
bool m_IsSessionKey;
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace ssu
|
namespace transport
|
||||||
{
|
{
|
||||||
SSUData::SSUData (SSUSession& session):
|
SSUData::SSUData (SSUSession& session):
|
||||||
m_Session (session), m_ResendTimer (session.m_Server.GetService ())
|
m_Session (session), m_ResendTimer (session.m_Server.GetService ())
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace ssu
|
namespace transport
|
||||||
{
|
{
|
||||||
|
|
||||||
const size_t SSU_MTU = 1484;
|
const size_t SSU_MTU = 1484;
|
||||||
|
|
161
Streaming.cpp
161
Streaming.cpp
|
@ -1,3 +1,4 @@
|
||||||
|
#include <cryptopp/gzip.h>
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "RouterInfo.h"
|
#include "RouterInfo.h"
|
||||||
#include "RouterContext.h"
|
#include "RouterContext.h"
|
||||||
|
@ -11,12 +12,12 @@ namespace i2p
|
||||||
namespace stream
|
namespace stream
|
||||||
{
|
{
|
||||||
Stream::Stream (boost::asio::io_service& service, StreamingDestination& local,
|
Stream::Stream (boost::asio::io_service& service, StreamingDestination& local,
|
||||||
const i2p::data::LeaseSet& remote): m_Service (service), m_SendStreamID (0),
|
const i2p::data::LeaseSet& remote, int port): m_Service (service), m_SendStreamID (0),
|
||||||
m_SequenceNumber (0), m_LastReceivedSequenceNumber (-1), m_IsOpen (false),
|
m_SequenceNumber (0), m_LastReceivedSequenceNumber (-1), m_IsOpen (false),
|
||||||
m_IsReset (false), m_IsAckSendScheduled (false), m_LocalDestination (local),
|
m_IsReset (false), m_IsAckSendScheduled (false), m_LocalDestination (local),
|
||||||
m_RemoteLeaseSet (&remote), m_RoutingSession (nullptr), m_ReceiveTimer (m_Service),
|
m_RemoteLeaseSet (&remote), m_RoutingSession (nullptr), m_ReceiveTimer (m_Service),
|
||||||
m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0),
|
m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0),
|
||||||
m_NumReceivedBytes (0)
|
m_NumReceivedBytes (0), m_Port (port)
|
||||||
{
|
{
|
||||||
m_RecvStreamID = i2p::context.GetRandomNumberGenerator ().GenerateWord32 ();
|
m_RecvStreamID = i2p::context.GetRandomNumberGenerator ().GenerateWord32 ();
|
||||||
UpdateCurrentRemoteLease ();
|
UpdateCurrentRemoteLease ();
|
||||||
|
@ -27,7 +28,7 @@ namespace stream
|
||||||
m_IsOpen (false), m_IsReset (false), m_IsAckSendScheduled (false), m_LocalDestination (local),
|
m_IsOpen (false), m_IsReset (false), m_IsAckSendScheduled (false), m_LocalDestination (local),
|
||||||
m_RemoteLeaseSet (nullptr), m_RoutingSession (nullptr), m_ReceiveTimer (m_Service),
|
m_RemoteLeaseSet (nullptr), m_RoutingSession (nullptr), m_ReceiveTimer (m_Service),
|
||||||
m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0),
|
m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0),
|
||||||
m_NumReceivedBytes (0)
|
m_NumReceivedBytes (0), m_Port (0)
|
||||||
{
|
{
|
||||||
m_RecvStreamID = i2p::context.GetRandomNumberGenerator ().GenerateWord32 ();
|
m_RecvStreamID = i2p::context.GetRandomNumberGenerator ().GenerateWord32 ();
|
||||||
}
|
}
|
||||||
|
@ -115,7 +116,7 @@ namespace stream
|
||||||
{
|
{
|
||||||
// we have received duplicate. Most likely our outbound tunnel is dead
|
// we have received duplicate. Most likely our outbound tunnel is dead
|
||||||
LogPrint ("Duplicate message ", receivedSeqn, " received");
|
LogPrint ("Duplicate message ", receivedSeqn, " received");
|
||||||
m_LocalDestination.ResetCurrentOutboundTunnel (); // pick another outbound tunnel
|
m_LocalDestination.GetOwner ().ResetCurrentOutboundTunnel (); // pick another outbound tunnel
|
||||||
UpdateCurrentRemoteLease (); // pick another lease
|
UpdateCurrentRemoteLease (); // pick another lease
|
||||||
SendQuickAck (); // resend ack for previous message again
|
SendQuickAck (); // resend ack for previous message again
|
||||||
delete packet; // packet dropped
|
delete packet; // packet dropped
|
||||||
|
@ -274,11 +275,11 @@ namespace stream
|
||||||
if (isNoAck) flags |= PACKET_FLAG_NO_ACK;
|
if (isNoAck) flags |= PACKET_FLAG_NO_ACK;
|
||||||
*(uint16_t *)(packet + size) = htobe16 (flags);
|
*(uint16_t *)(packet + size) = htobe16 (flags);
|
||||||
size += 2; // flags
|
size += 2; // flags
|
||||||
size_t identityLen = m_LocalDestination.GetIdentity ().GetFullLen ();
|
size_t identityLen = m_LocalDestination.GetOwner ().GetIdentity ().GetFullLen ();
|
||||||
size_t signatureLen = m_LocalDestination.GetIdentity ().GetSignatureLen ();
|
size_t signatureLen = m_LocalDestination.GetOwner ().GetIdentity ().GetSignatureLen ();
|
||||||
*(uint16_t *)(packet + size) = htobe16 (identityLen + signatureLen + 2); // identity + signature + packet size
|
*(uint16_t *)(packet + size) = htobe16 (identityLen + signatureLen + 2); // identity + signature + packet size
|
||||||
size += 2; // options size
|
size += 2; // options size
|
||||||
m_LocalDestination.GetIdentity ().ToBuffer (packet + size, identityLen);
|
m_LocalDestination.GetOwner ().GetIdentity ().ToBuffer (packet + size, identityLen);
|
||||||
size += identityLen; // from
|
size += identityLen; // from
|
||||||
*(uint16_t *)(packet + size) = htobe16 (STREAMING_MTU);
|
*(uint16_t *)(packet + size) = htobe16 (STREAMING_MTU);
|
||||||
size += 2; // max packet size
|
size += 2; // max packet size
|
||||||
|
@ -291,7 +292,7 @@ namespace stream
|
||||||
buf += sentLen;
|
buf += sentLen;
|
||||||
len -= sentLen;
|
len -= sentLen;
|
||||||
size += sentLen; // payload
|
size += sentLen; // payload
|
||||||
m_LocalDestination.Sign (packet, size, signature);
|
m_LocalDestination.GetOwner ().Sign (packet, size, signature);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -362,13 +363,13 @@ namespace stream
|
||||||
size++; // resend delay
|
size++; // resend delay
|
||||||
*(uint16_t *)(packet + size) = htobe16 (PACKET_FLAG_CLOSE | PACKET_FLAG_SIGNATURE_INCLUDED);
|
*(uint16_t *)(packet + size) = htobe16 (PACKET_FLAG_CLOSE | PACKET_FLAG_SIGNATURE_INCLUDED);
|
||||||
size += 2; // flags
|
size += 2; // flags
|
||||||
size_t signatureLen = m_LocalDestination.GetIdentity ().GetSignatureLen ();
|
size_t signatureLen = m_LocalDestination.GetOwner ().GetIdentity ().GetSignatureLen ();
|
||||||
*(uint16_t *)(packet + size) = htobe16 (signatureLen); // signature only
|
*(uint16_t *)(packet + size) = htobe16 (signatureLen); // signature only
|
||||||
size += 2; // options size
|
size += 2; // options size
|
||||||
uint8_t * signature = packet + size;
|
uint8_t * signature = packet + size;
|
||||||
memset (packet + size, 0, signatureLen);
|
memset (packet + size, 0, signatureLen);
|
||||||
size += signatureLen; // signature
|
size += signatureLen; // signature
|
||||||
m_LocalDestination.Sign (packet, size, signature);
|
m_LocalDestination.GetOwner ().Sign (packet, size, signature);
|
||||||
|
|
||||||
p->len = size;
|
p->len = size;
|
||||||
SendPacket (p);
|
SendPacket (p);
|
||||||
|
@ -440,8 +441,7 @@ namespace stream
|
||||||
std::vector<i2p::tunnel::TunnelMessageBlock> msgs;
|
std::vector<i2p::tunnel::TunnelMessageBlock> msgs;
|
||||||
for (auto it: packets)
|
for (auto it: packets)
|
||||||
{
|
{
|
||||||
auto msg = m_RoutingSession->WrapSingleMessage (
|
auto msg = m_RoutingSession->WrapSingleMessage (CreateDataMessage (it->GetBuffer (), it->GetLength ()));
|
||||||
m_LocalDestination.CreateDataMessage (it->GetBuffer (), it->GetLength ()));
|
|
||||||
msgs.push_back (i2p::tunnel::TunnelMessageBlock
|
msgs.push_back (i2p::tunnel::TunnelMessageBlock
|
||||||
{
|
{
|
||||||
i2p::tunnel::eDeliveryTypeTunnel,
|
i2p::tunnel::eDeliveryTypeTunnel,
|
||||||
|
@ -450,7 +450,7 @@ namespace stream
|
||||||
});
|
});
|
||||||
m_NumSentBytes += it->GetLength ();
|
m_NumSentBytes += it->GetLength ();
|
||||||
}
|
}
|
||||||
m_LocalDestination.SendTunnelDataMsgs (msgs);
|
m_LocalDestination.GetOwner ().SendTunnelDataMsgs (msgs);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint ("All leases are expired");
|
LogPrint ("All leases are expired");
|
||||||
|
@ -484,7 +484,7 @@ namespace stream
|
||||||
}
|
}
|
||||||
if (packets.size () > 0)
|
if (packets.size () > 0)
|
||||||
{
|
{
|
||||||
m_LocalDestination.ResetCurrentOutboundTunnel (); // pick another outbound tunnel
|
m_LocalDestination.GetOwner ().ResetCurrentOutboundTunnel (); // pick another outbound tunnel
|
||||||
UpdateCurrentRemoteLease (); // pick another lease
|
UpdateCurrentRemoteLease (); // pick another lease
|
||||||
SendPackets (packets);
|
SendPackets (packets);
|
||||||
}
|
}
|
||||||
|
@ -506,14 +506,14 @@ namespace stream
|
||||||
{
|
{
|
||||||
if (!m_RemoteLeaseSet)
|
if (!m_RemoteLeaseSet)
|
||||||
{
|
{
|
||||||
m_RemoteLeaseSet = m_LocalDestination.FindLeaseSet (m_RemoteIdentity.GetIdentHash ());
|
m_RemoteLeaseSet = m_LocalDestination.GetOwner ().FindLeaseSet (m_RemoteIdentity.GetIdentHash ());
|
||||||
if (!m_RemoteLeaseSet)
|
if (!m_RemoteLeaseSet)
|
||||||
LogPrint ("LeaseSet ", m_RemoteIdentity.GetIdentHash ().ToBase64 (), " not found");
|
LogPrint ("LeaseSet ", m_RemoteIdentity.GetIdentHash ().ToBase64 (), " not found");
|
||||||
}
|
}
|
||||||
if (m_RemoteLeaseSet)
|
if (m_RemoteLeaseSet)
|
||||||
{
|
{
|
||||||
if (!m_RoutingSession)
|
if (!m_RoutingSession)
|
||||||
m_RoutingSession = m_LocalDestination.GetRoutingSession (*m_RemoteLeaseSet, 32);
|
m_RoutingSession = m_LocalDestination.GetOwner ().GetRoutingSession (*m_RemoteLeaseSet, 32);
|
||||||
auto leases = m_RemoteLeaseSet->GetNonExpiredLeases ();
|
auto leases = m_RemoteLeaseSet->GetNonExpiredLeases ();
|
||||||
if (!leases.empty ())
|
if (!leases.empty ())
|
||||||
{
|
{
|
||||||
|
@ -522,12 +522,139 @@ namespace stream
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_RemoteLeaseSet = m_LocalDestination.FindLeaseSet (m_RemoteIdentity.GetIdentHash ()); // re-request expired
|
m_RemoteLeaseSet = m_LocalDestination.GetOwner ().FindLeaseSet (m_RemoteIdentity.GetIdentHash ()); // re-request expired
|
||||||
m_CurrentRemoteLease.endDate = 0;
|
m_CurrentRemoteLease.endDate = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_CurrentRemoteLease.endDate = 0;
|
m_CurrentRemoteLease.endDate = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
I2NPMessage * Stream::CreateDataMessage (const uint8_t * payload, size_t len)
|
||||||
|
{
|
||||||
|
I2NPMessage * msg = NewI2NPShortMessage ();
|
||||||
|
CryptoPP::Gzip compressor;
|
||||||
|
if (len <= i2p::stream::COMPRESSION_THRESHOLD_SIZE)
|
||||||
|
compressor.SetDeflateLevel (CryptoPP::Gzip::MIN_DEFLATE_LEVEL);
|
||||||
|
else
|
||||||
|
compressor.SetDeflateLevel (CryptoPP::Gzip::DEFAULT_DEFLATE_LEVEL);
|
||||||
|
compressor.Put (payload, len);
|
||||||
|
compressor.MessageEnd();
|
||||||
|
int size = compressor.MaxRetrievable ();
|
||||||
|
uint8_t * buf = msg->GetPayload ();
|
||||||
|
*(uint32_t *)buf = htobe32 (size); // length
|
||||||
|
buf += 4;
|
||||||
|
compressor.Get (buf, size);
|
||||||
|
*(uint16_t *)(buf + 4) = 0; // source port
|
||||||
|
*(uint16_t *)(buf + 6) = htobe16 (m_Port); // destination port
|
||||||
|
buf[9] = i2p::client::PROTOCOL_TYPE_STREAMING; // streaming protocol
|
||||||
|
msg->len += size + 4;
|
||||||
|
FillI2NPMessageHeader (msg, eI2NPData);
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamingDestination::Start ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamingDestination::Stop ()
|
||||||
|
{
|
||||||
|
ResetAcceptor ();
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> l(m_StreamsMutex);
|
||||||
|
for (auto it: m_Streams)
|
||||||
|
delete it.second;
|
||||||
|
m_Streams.clear ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamingDestination::HandleNextPacket (Packet * packet)
|
||||||
|
{
|
||||||
|
uint32_t sendStreamID = packet->GetSendStreamID ();
|
||||||
|
if (sendStreamID)
|
||||||
|
{
|
||||||
|
auto it = m_Streams.find (sendStreamID);
|
||||||
|
if (it != m_Streams.end ())
|
||||||
|
it->second->HandleNextPacket (packet);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrint ("Unknown stream ", sendStreamID);
|
||||||
|
delete packet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // new incoming stream
|
||||||
|
{
|
||||||
|
auto incomingStream = CreateNewIncomingStream ();
|
||||||
|
incomingStream->HandleNextPacket (packet);
|
||||||
|
if (m_Acceptor != nullptr)
|
||||||
|
m_Acceptor (incomingStream);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrint ("Acceptor for incoming stream is not set");
|
||||||
|
DeleteStream (incomingStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream * StreamingDestination::CreateNewOutgoingStream (const i2p::data::LeaseSet& remote, int port)
|
||||||
|
{
|
||||||
|
Stream * s = new Stream (*m_Owner.GetService (), *this, remote, port);
|
||||||
|
std::unique_lock<std::mutex> l(m_StreamsMutex);
|
||||||
|
m_Streams[s->GetRecvStreamID ()] = s;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream * StreamingDestination::CreateNewIncomingStream ()
|
||||||
|
{
|
||||||
|
Stream * s = new Stream (*m_Owner.GetService (), *this);
|
||||||
|
std::unique_lock<std::mutex> l(m_StreamsMutex);
|
||||||
|
m_Streams[s->GetRecvStreamID ()] = s;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamingDestination::DeleteStream (Stream * stream)
|
||||||
|
{
|
||||||
|
if (stream)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> l(m_StreamsMutex);
|
||||||
|
auto it = m_Streams.find (stream->GetRecvStreamID ());
|
||||||
|
if (it != m_Streams.end ())
|
||||||
|
{
|
||||||
|
m_Streams.erase (it);
|
||||||
|
if (m_Owner.GetService ())
|
||||||
|
m_Owner.GetService ()->post ([stream](void) { delete stream; });
|
||||||
|
else
|
||||||
|
delete stream;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StreamingDestination::HandleDataMessagePayload (const uint8_t * buf, size_t len)
|
||||||
|
{
|
||||||
|
// unzip it
|
||||||
|
CryptoPP::Gunzip decompressor;
|
||||||
|
decompressor.Put (buf, len);
|
||||||
|
decompressor.MessageEnd();
|
||||||
|
Packet * uncompressed = new Packet;
|
||||||
|
uncompressed->offset = 0;
|
||||||
|
uncompressed->len = decompressor.MaxRetrievable ();
|
||||||
|
if (uncompressed->len <= MAX_PACKET_SIZE)
|
||||||
|
{
|
||||||
|
decompressor.Get (uncompressed->buf, uncompressed->len);
|
||||||
|
HandleNextPacket (uncompressed);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrint ("Received packet size ", uncompressed->len, " exceeds max packet size. Skipped");
|
||||||
|
delete uncompressed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeleteStream (Stream * stream)
|
||||||
|
{
|
||||||
|
if (stream)
|
||||||
|
stream->GetLocalDestination ().DeleteStream (stream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
49
Streaming.h
49
Streaming.h
|
@ -18,6 +18,10 @@
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
|
namespace client
|
||||||
|
{
|
||||||
|
class ClientDestination;
|
||||||
|
}
|
||||||
namespace stream
|
namespace stream
|
||||||
{
|
{
|
||||||
const uint16_t PACKET_FLAG_SYNCHRONIZE = 0x0001;
|
const uint16_t PACKET_FLAG_SYNCHRONIZE = 0x0001;
|
||||||
|
@ -78,7 +82,8 @@ namespace stream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Stream (boost::asio::io_service& service, StreamingDestination& local, const i2p::data::LeaseSet& remote); // outgoing
|
Stream (boost::asio::io_service& service, StreamingDestination& local,
|
||||||
|
const i2p::data::LeaseSet& remote, int port = 0); // outgoing
|
||||||
Stream (boost::asio::io_service& service, StreamingDestination& local); // incoming
|
Stream (boost::asio::io_service& service, StreamingDestination& local); // incoming
|
||||||
|
|
||||||
~Stream ();
|
~Stream ();
|
||||||
|
@ -122,6 +127,8 @@ namespace stream
|
||||||
void ScheduleResend ();
|
void ScheduleResend ();
|
||||||
void HandleResendTimer (const boost::system::error_code& ecode);
|
void HandleResendTimer (const boost::system::error_code& ecode);
|
||||||
void HandleAckSendTimer (const boost::system::error_code& ecode);
|
void HandleAckSendTimer (const boost::system::error_code& ecode);
|
||||||
|
|
||||||
|
I2NPMessage * CreateDataMessage (const uint8_t * payload, size_t len);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -139,8 +146,48 @@ namespace stream
|
||||||
std::set<Packet *, PacketCmp> m_SentPackets;
|
std::set<Packet *, PacketCmp> m_SentPackets;
|
||||||
boost::asio::deadline_timer m_ReceiveTimer, m_ResendTimer, m_AckSendTimer;
|
boost::asio::deadline_timer m_ReceiveTimer, m_ResendTimer, m_AckSendTimer;
|
||||||
size_t m_NumSentBytes, m_NumReceivedBytes;
|
size_t m_NumSentBytes, m_NumReceivedBytes;
|
||||||
|
uint16_t m_Port;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class StreamingDestination
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
StreamingDestination (i2p::client::ClientDestination& owner): m_Owner (owner) {};
|
||||||
|
~StreamingDestination () {};
|
||||||
|
|
||||||
|
void Start ();
|
||||||
|
void Stop ();
|
||||||
|
|
||||||
|
Stream * CreateNewOutgoingStream (const i2p::data::LeaseSet& remote, int port = 0);
|
||||||
|
void DeleteStream (Stream * stream);
|
||||||
|
void SetAcceptor (const std::function<void (Stream *)>& acceptor) { m_Acceptor = acceptor; };
|
||||||
|
void ResetAcceptor () { m_Acceptor = nullptr; };
|
||||||
|
bool IsAcceptorSet () const { return m_Acceptor != nullptr; };
|
||||||
|
i2p::client::ClientDestination& GetOwner () { return m_Owner; };
|
||||||
|
|
||||||
|
void HandleDataMessagePayload (const uint8_t * buf, size_t len);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void HandleNextPacket (Packet * packet);
|
||||||
|
Stream * CreateNewIncomingStream ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
i2p::client::ClientDestination& m_Owner;
|
||||||
|
std::mutex m_StreamsMutex;
|
||||||
|
std::map<uint32_t, Stream *> m_Streams;
|
||||||
|
std::function<void (Stream *)> m_Acceptor;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// for HTTP only
|
||||||
|
const decltype(m_Streams)& GetStreams () const { return m_Streams; };
|
||||||
|
};
|
||||||
|
|
||||||
|
void DeleteStream (Stream * stream);
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
template<typename Buffer, typename ReceiveHandler>
|
template<typename Buffer, typename ReceiveHandler>
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace tunnel
|
||||||
*(uint32_t *)(tunnelMsg->GetPayload ()) = htobe32 (m_NextTunnelID);
|
*(uint32_t *)(tunnelMsg->GetPayload ()) = htobe32 (m_NextTunnelID);
|
||||||
FillI2NPMessageHeader (tunnelMsg, eI2NPTunnelData);
|
FillI2NPMessageHeader (tunnelMsg, eI2NPTunnelData);
|
||||||
|
|
||||||
i2p::transports.SendMessage (m_NextIdent, tunnelMsg);
|
i2p::transport::transports.SendMessage (m_NextIdent, tunnelMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransitTunnel::SendTunnelDataMsg (i2p::I2NPMessage * msg)
|
void TransitTunnel::SendTunnelDataMsg (i2p::I2NPMessage * msg)
|
||||||
|
|
43
TransportSession.h
Normal file
43
TransportSession.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef TRANSPORT_SESSION_H__
|
||||||
|
#define TRANSPORT_SESSION_H__
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include "Identity.h"
|
||||||
|
#include "RouterInfo.h"
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace transport
|
||||||
|
{
|
||||||
|
struct DHKeysPair // transient keys for transport sessions
|
||||||
|
{
|
||||||
|
uint8_t publicKey[256];
|
||||||
|
uint8_t privateKey[256];
|
||||||
|
};
|
||||||
|
|
||||||
|
class TransportSession
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
TransportSession (const i2p::data::RouterInfo * in_RemoteRouter):
|
||||||
|
m_RemoteRouter (in_RemoteRouter), m_DHKeysPair (nullptr)
|
||||||
|
{
|
||||||
|
if (m_RemoteRouter)
|
||||||
|
m_RemoteIdentity = m_RemoteRouter->GetRouterIdentity ();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~TransportSession () { delete m_DHKeysPair; };
|
||||||
|
|
||||||
|
const i2p::data::RouterInfo * GetRemoteRouter () { return m_RemoteRouter; };
|
||||||
|
const i2p::data::IdentityEx& GetRemoteIdentity () { return m_RemoteIdentity; };
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
const i2p::data::RouterInfo * m_RemoteRouter;
|
||||||
|
i2p::data::IdentityEx m_RemoteIdentity;
|
||||||
|
DHKeysPair * m_DHKeysPair; // X - for client and Y - for server
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,5 +1,7 @@
|
||||||
|
#include <cryptopp/dh.h>
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "CryptoConst.h"
|
||||||
#include "RouterContext.h"
|
#include "RouterContext.h"
|
||||||
#include "I2NPProtocol.h"
|
#include "I2NPProtocol.h"
|
||||||
#include "NetDb.h"
|
#include "NetDb.h"
|
||||||
|
@ -9,6 +11,13 @@ using namespace i2p::data;
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
|
namespace transport
|
||||||
|
{
|
||||||
|
DHKeysPairSupplier::DHKeysPairSupplier (int size):
|
||||||
|
m_QueueSize (size), m_IsRunning (false), m_Thread (nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
DHKeysPairSupplier::~DHKeysPairSupplier ()
|
DHKeysPairSupplier::~DHKeysPairSupplier ()
|
||||||
{
|
{
|
||||||
Stop ();
|
Stop ();
|
||||||
|
@ -48,17 +57,18 @@ namespace i2p
|
||||||
{
|
{
|
||||||
if (num > 0)
|
if (num > 0)
|
||||||
{
|
{
|
||||||
|
CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
|
||||||
for (int i = 0; i < num; i++)
|
for (int i = 0; i < num; i++)
|
||||||
{
|
{
|
||||||
i2p::data::DHKeysPair * pair = new i2p::data::DHKeysPair ();
|
i2p::transport::DHKeysPair * pair = new i2p::transport::DHKeysPair ();
|
||||||
i2p::data::CreateRandomDHKeysPair (pair);
|
dh.GenerateKeyPair(m_Rnd, pair->privateKey, pair->publicKey);
|
||||||
std::unique_lock<std::mutex> l(m_AcquiredMutex);
|
std::unique_lock<std::mutex> l(m_AcquiredMutex);
|
||||||
m_Queue.push (pair);
|
m_Queue.push (pair);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i2p::data::DHKeysPair * DHKeysPairSupplier::Acquire ()
|
DHKeysPair * DHKeysPairSupplier::Acquire ()
|
||||||
{
|
{
|
||||||
if (!m_Queue.empty ())
|
if (!m_Queue.empty ())
|
||||||
{
|
{
|
||||||
|
@ -70,13 +80,14 @@ namespace i2p
|
||||||
}
|
}
|
||||||
else // queue is empty, create new
|
else // queue is empty, create new
|
||||||
{
|
{
|
||||||
i2p::data::DHKeysPair * pair = new i2p::data::DHKeysPair ();
|
DHKeysPair * pair = new DHKeysPair ();
|
||||||
i2p::data::CreateRandomDHKeysPair (pair);
|
CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
|
||||||
|
dh.GenerateKeyPair(m_Rnd, pair->privateKey, pair->publicKey);
|
||||||
return pair;
|
return pair;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DHKeysPairSupplier::Return (i2p::data::DHKeysPair * pair)
|
void DHKeysPairSupplier::Return (DHKeysPair * pair)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> l(m_AcquiredMutex);
|
std::unique_lock<std::mutex> l(m_AcquiredMutex);
|
||||||
m_Queue.push (pair);
|
m_Queue.push (pair);
|
||||||
|
@ -85,7 +96,7 @@ namespace i2p
|
||||||
Transports transports;
|
Transports transports;
|
||||||
|
|
||||||
Transports::Transports ():
|
Transports::Transports ():
|
||||||
m_Thread (nullptr), m_Work (m_Service), m_NTCPAcceptor (nullptr),
|
m_Thread (nullptr), m_Work (m_Service), m_NTCPAcceptor (nullptr), m_NTCPV6Acceptor (nullptr),
|
||||||
m_SSUServer (nullptr), m_DHKeysPairSupplier (5) // 5 pre-generated keys
|
m_SSUServer (nullptr), m_DHKeysPairSupplier (5) // 5 pre-generated keys
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -110,15 +121,26 @@ namespace i2p
|
||||||
boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), address.port));
|
boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), address.port));
|
||||||
|
|
||||||
LogPrint ("Start listening TCP port ", address.port);
|
LogPrint ("Start listening TCP port ", address.port);
|
||||||
auto conn = new i2p::ntcp::NTCPServerConnection (m_Service);
|
auto conn = new NTCPServerConnection (m_Service);
|
||||||
m_NTCPAcceptor->async_accept(conn->GetSocket (), boost::bind (&Transports::HandleAccept, this,
|
m_NTCPAcceptor->async_accept(conn->GetSocket (), boost::bind (&Transports::HandleAccept, this,
|
||||||
conn, boost::asio::placeholders::error));
|
conn, boost::asio::placeholders::error));
|
||||||
|
|
||||||
|
if (context.SupportsV6 ())
|
||||||
|
{
|
||||||
|
m_NTCPV6Acceptor = new boost::asio::ip::tcp::acceptor (m_Service,
|
||||||
|
boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), address.port));
|
||||||
|
|
||||||
|
LogPrint ("Start listening V6 TCP port ", address.port);
|
||||||
|
auto conn = new NTCPServerConnection (m_Service);
|
||||||
|
m_NTCPV6Acceptor->async_accept(conn->GetSocket (), boost::bind (&Transports::HandleAcceptV6,
|
||||||
|
this, conn, boost::asio::placeholders::error));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (address.transportStyle == RouterInfo::eTransportSSU)
|
else if (address.transportStyle == RouterInfo::eTransportSSU)
|
||||||
{
|
{
|
||||||
if (!m_SSUServer)
|
if (!m_SSUServer)
|
||||||
{
|
{
|
||||||
m_SSUServer = new i2p::ssu::SSUServer (address.port);
|
m_SSUServer = new SSUServer (address.port);
|
||||||
LogPrint ("Start listening UDP port ", address.port);
|
LogPrint ("Start listening UDP port ", address.port);
|
||||||
m_SSUServer->Start ();
|
m_SSUServer->Start ();
|
||||||
DetectExternalIP ();
|
DetectExternalIP ();
|
||||||
|
@ -143,6 +165,8 @@ namespace i2p
|
||||||
m_NTCPSessions.clear ();
|
m_NTCPSessions.clear ();
|
||||||
delete m_NTCPAcceptor;
|
delete m_NTCPAcceptor;
|
||||||
m_NTCPAcceptor = nullptr;
|
m_NTCPAcceptor = nullptr;
|
||||||
|
delete m_NTCPV6Acceptor;
|
||||||
|
m_NTCPV6Acceptor = nullptr;
|
||||||
|
|
||||||
m_DHKeysPairSupplier.Stop ();
|
m_DHKeysPairSupplier.Stop ();
|
||||||
m_IsRunning = false;
|
m_IsRunning = false;
|
||||||
|
@ -170,19 +194,19 @@ namespace i2p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Transports::AddNTCPSession (i2p::ntcp::NTCPSession * session)
|
void Transports::AddNTCPSession (NTCPSession * session)
|
||||||
{
|
{
|
||||||
if (session)
|
if (session)
|
||||||
m_NTCPSessions[session->GetRemoteRouterInfo ().GetIdentHash ()] = session;
|
m_NTCPSessions[session->GetRemoteIdentity ().GetIdentHash ()] = session;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Transports::RemoveNTCPSession (i2p::ntcp::NTCPSession * session)
|
void Transports::RemoveNTCPSession (NTCPSession * session)
|
||||||
{
|
{
|
||||||
if (session)
|
if (session)
|
||||||
m_NTCPSessions.erase (session->GetRemoteRouterInfo ().GetIdentHash ());
|
m_NTCPSessions.erase (session->GetRemoteIdentity ().GetIdentHash ());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Transports::HandleAccept (i2p::ntcp::NTCPServerConnection * conn, const boost::system::error_code& error)
|
void Transports::HandleAccept (NTCPServerConnection * conn, const boost::system::error_code& error)
|
||||||
{
|
{
|
||||||
if (!error)
|
if (!error)
|
||||||
{
|
{
|
||||||
|
@ -194,13 +218,31 @@ namespace i2p
|
||||||
|
|
||||||
if (error != boost::asio::error::operation_aborted)
|
if (error != boost::asio::error::operation_aborted)
|
||||||
{
|
{
|
||||||
conn = new i2p::ntcp::NTCPServerConnection (m_Service);
|
conn = new NTCPServerConnection (m_Service);
|
||||||
m_NTCPAcceptor->async_accept(conn->GetSocket (), boost::bind (&Transports::HandleAccept, this,
|
m_NTCPAcceptor->async_accept(conn->GetSocket (), boost::bind (&Transports::HandleAccept, this,
|
||||||
conn, boost::asio::placeholders::error));
|
conn, boost::asio::placeholders::error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i2p::ntcp::NTCPSession * Transports::GetNextNTCPSession ()
|
void Transports::HandleAcceptV6 (NTCPServerConnection * conn, const boost::system::error_code& error)
|
||||||
|
{
|
||||||
|
if (!error)
|
||||||
|
{
|
||||||
|
LogPrint ("Connected from ", conn->GetSocket ().remote_endpoint().address ().to_string ());
|
||||||
|
conn->ServerLogin ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
delete conn;
|
||||||
|
|
||||||
|
if (error != boost::asio::error::operation_aborted)
|
||||||
|
{
|
||||||
|
conn = new NTCPServerConnection (m_Service);
|
||||||
|
m_NTCPV6Acceptor->async_accept(conn->GetSocket (), boost::bind (&Transports::HandleAcceptV6, this,
|
||||||
|
conn, boost::asio::placeholders::error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NTCPSession * Transports::GetNextNTCPSession ()
|
||||||
{
|
{
|
||||||
for (auto session: m_NTCPSessions)
|
for (auto session: m_NTCPSessions)
|
||||||
if (session.second->IsEstablished ())
|
if (session.second->IsEstablished ())
|
||||||
|
@ -208,7 +250,7 @@ namespace i2p
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
i2p::ntcp::NTCPSession * Transports::FindNTCPSession (const i2p::data::IdentHash& ident)
|
NTCPSession * Transports::FindNTCPSession (const i2p::data::IdentHash& ident)
|
||||||
{
|
{
|
||||||
auto it = m_NTCPSessions.find (ident);
|
auto it = m_NTCPSessions.find (ident);
|
||||||
if (it != m_NTCPSessions.end ())
|
if (it != m_NTCPSessions.end ())
|
||||||
|
@ -242,10 +284,10 @@ namespace i2p
|
||||||
{
|
{
|
||||||
// existing session not found. create new
|
// existing session not found. create new
|
||||||
// try NTCP first if message size < 16K
|
// try NTCP first if message size < 16K
|
||||||
auto address = r->GetNTCPAddress ();
|
auto address = r->GetNTCPAddress (!context.SupportsV6 ());
|
||||||
if (address && !r->UsesIntroducer () && !r->IsUnreachable () && msg->GetLength () < i2p::ntcp::NTCP_MAX_MESSAGE_SIZE)
|
if (address && !r->UsesIntroducer () && !r->IsUnreachable () && msg->GetLength () < NTCP_MAX_MESSAGE_SIZE)
|
||||||
{
|
{
|
||||||
auto s = new i2p::ntcp::NTCPClient (m_Service, address->host, address->port, *r);
|
auto s = new NTCPClient (m_Service, address->host, address->port, *r);
|
||||||
AddNTCPSession (s);
|
AddNTCPSession (s);
|
||||||
s->SendI2NPMessage (msg);
|
s->SendI2NPMessage (msg);
|
||||||
}
|
}
|
||||||
|
@ -318,15 +360,16 @@ namespace i2p
|
||||||
m_SSUServer->GetSession (router, true); // peer test
|
m_SSUServer->GetSession (router, true); // peer test
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DHKeysPair * Transports::GetNextDHKeysPair ()
|
||||||
i2p::data::DHKeysPair * Transports::GetNextDHKeysPair ()
|
|
||||||
{
|
{
|
||||||
return m_DHKeysPairSupplier.Acquire ();
|
return m_DHKeysPairSupplier.Acquire ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Transports::ReuseDHKeysPair (i2p::data::DHKeysPair * pair)
|
void Transports::ReuseDHKeysPair (DHKeysPair * pair)
|
||||||
{
|
{
|
||||||
m_DHKeysPairSupplier.Return (pair);
|
m_DHKeysPairSupplier.Return (pair);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
37
Transports.h
37
Transports.h
|
@ -8,7 +8,9 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <cryptopp/osrng.h>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
|
#include "TransportSession.h"
|
||||||
#include "NTCPSession.h"
|
#include "NTCPSession.h"
|
||||||
#include "SSU.h"
|
#include "SSU.h"
|
||||||
#include "RouterInfo.h"
|
#include "RouterInfo.h"
|
||||||
|
@ -16,17 +18,19 @@
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace transport
|
||||||
{
|
{
|
||||||
class DHKeysPairSupplier
|
class DHKeysPairSupplier
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DHKeysPairSupplier (int size): m_QueueSize (size), m_IsRunning (false), m_Thread (nullptr) {};
|
DHKeysPairSupplier (int size);
|
||||||
~DHKeysPairSupplier ();
|
~DHKeysPairSupplier ();
|
||||||
void Start ();
|
void Start ();
|
||||||
void Stop ();
|
void Stop ();
|
||||||
i2p::data::DHKeysPair * Acquire ();
|
DHKeysPair * Acquire ();
|
||||||
void Return (i2p::data::DHKeysPair * pair);
|
void Return (DHKeysPair * pair);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -36,12 +40,13 @@ namespace i2p
|
||||||
private:
|
private:
|
||||||
|
|
||||||
const int m_QueueSize;
|
const int m_QueueSize;
|
||||||
std::queue<i2p::data::DHKeysPair *> m_Queue;
|
std::queue<DHKeysPair *> m_Queue;
|
||||||
|
|
||||||
bool m_IsRunning;
|
bool m_IsRunning;
|
||||||
std::thread * m_Thread;
|
std::thread * m_Thread;
|
||||||
std::condition_variable m_Acquired;
|
std::condition_variable m_Acquired;
|
||||||
std::mutex m_AcquiredMutex;
|
std::mutex m_AcquiredMutex;
|
||||||
|
CryptoPP::AutoSeededRandomPool m_Rnd;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Transports
|
class Transports
|
||||||
|
@ -55,14 +60,14 @@ namespace i2p
|
||||||
void Stop ();
|
void Stop ();
|
||||||
|
|
||||||
boost::asio::io_service& GetService () { return m_Service; };
|
boost::asio::io_service& GetService () { return m_Service; };
|
||||||
i2p::data::DHKeysPair * GetNextDHKeysPair ();
|
i2p::transport::DHKeysPair * GetNextDHKeysPair ();
|
||||||
void ReuseDHKeysPair (i2p::data::DHKeysPair * pair);
|
void ReuseDHKeysPair (DHKeysPair * pair);
|
||||||
|
|
||||||
void AddNTCPSession (i2p::ntcp::NTCPSession * session);
|
void AddNTCPSession (NTCPSession * session);
|
||||||
void RemoveNTCPSession (i2p::ntcp::NTCPSession * session);
|
void RemoveNTCPSession (NTCPSession * session);
|
||||||
|
|
||||||
i2p::ntcp::NTCPSession * GetNextNTCPSession ();
|
NTCPSession * GetNextNTCPSession ();
|
||||||
i2p::ntcp::NTCPSession * FindNTCPSession (const i2p::data::IdentHash& ident);
|
NTCPSession * FindNTCPSession (const i2p::data::IdentHash& ident);
|
||||||
|
|
||||||
void SendMessage (const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg);
|
void SendMessage (const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg);
|
||||||
void CloseSession (const i2p::data::RouterInfo * router);
|
void CloseSession (const i2p::data::RouterInfo * router);
|
||||||
|
@ -70,7 +75,8 @@ namespace i2p
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void Run ();
|
void Run ();
|
||||||
void HandleAccept (i2p::ntcp::NTCPServerConnection * conn, const boost::system::error_code& error);
|
void HandleAccept (NTCPServerConnection * conn, const boost::system::error_code& error);
|
||||||
|
void HandleAcceptV6 (NTCPServerConnection * conn, const boost::system::error_code& error);
|
||||||
void HandleResendTimer (const boost::system::error_code& ecode, boost::asio::deadline_timer * timer,
|
void HandleResendTimer (const boost::system::error_code& ecode, boost::asio::deadline_timer * timer,
|
||||||
const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg);
|
const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg);
|
||||||
void PostMessage (const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg);
|
void PostMessage (const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg);
|
||||||
|
@ -84,10 +90,10 @@ namespace i2p
|
||||||
std::thread * m_Thread;
|
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;
|
||||||
boost::asio::ip::tcp::acceptor * m_NTCPAcceptor;
|
boost::asio::ip::tcp::acceptor * m_NTCPAcceptor, * m_NTCPV6Acceptor;
|
||||||
|
|
||||||
std::map<i2p::data::IdentHash, i2p::ntcp::NTCPSession *> m_NTCPSessions;
|
std::map<i2p::data::IdentHash, NTCPSession *> m_NTCPSessions;
|
||||||
i2p::ssu::SSUServer * m_SSUServer;
|
SSUServer * m_SSUServer;
|
||||||
|
|
||||||
DHKeysPairSupplier m_DHKeysPairSupplier;
|
DHKeysPairSupplier m_DHKeysPairSupplier;
|
||||||
|
|
||||||
|
@ -95,10 +101,11 @@ namespace i2p
|
||||||
|
|
||||||
// for HTTP only
|
// for HTTP only
|
||||||
const decltype(m_NTCPSessions)& GetNTCPSessions () const { return m_NTCPSessions; };
|
const decltype(m_NTCPSessions)& GetNTCPSessions () const { return m_NTCPSessions; };
|
||||||
const i2p::ssu::SSUServer * GetSSUServer () const { return m_SSUServer; };
|
const SSUServer * GetSSUServer () const { return m_SSUServer; };
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Transports transports;
|
extern Transports transports;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -92,7 +92,7 @@ namespace tunnel
|
||||||
if (outboundTunnel)
|
if (outboundTunnel)
|
||||||
outboundTunnel->SendTunnelDataMsg (GetNextIdentHash (), 0, msg);
|
outboundTunnel->SendTunnelDataMsg (GetNextIdentHash (), 0, msg);
|
||||||
else
|
else
|
||||||
i2p::transports.SendMessage (GetNextIdentHash (), msg);
|
i2p::transport::transports.SendMessage (GetNextIdentHash (), msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Tunnel::HandleTunnelBuildResponse (uint8_t * msg, size_t len)
|
bool Tunnel::HandleTunnelBuildResponse (uint8_t * msg, size_t len)
|
||||||
|
|
|
@ -235,7 +235,7 @@ namespace tunnel
|
||||||
i2p::HandleI2NPMessage (msg.data);
|
i2p::HandleI2NPMessage (msg.data);
|
||||||
break;
|
break;
|
||||||
case eDeliveryTypeTunnel:
|
case eDeliveryTypeTunnel:
|
||||||
i2p::transports.SendMessage (msg.hash, i2p::CreateTunnelGatewayMsg (msg.tunnelID, msg.data));
|
i2p::transport::transports.SendMessage (msg.hash, i2p::CreateTunnelGatewayMsg (msg.tunnelID, msg.data));
|
||||||
break;
|
break;
|
||||||
case eDeliveryTypeRouter:
|
case eDeliveryTypeRouter:
|
||||||
if (msg.hash == i2p::context.GetRouterInfo ().GetIdentHash ()) // check if message is sent to us
|
if (msg.hash == i2p::context.GetRouterInfo ().GetIdentHash ()) // check if message is sent to us
|
||||||
|
@ -253,7 +253,7 @@ namespace tunnel
|
||||||
*ds = *(msg.data);
|
*ds = *(msg.data);
|
||||||
i2p::data::netdb.PostI2NPMsg (ds);
|
i2p::data::netdb.PostI2NPMsg (ds);
|
||||||
}
|
}
|
||||||
i2p::transports.SendMessage (msg.hash, msg.data);
|
i2p::transport::transports.SendMessage (msg.hash, msg.data);
|
||||||
}
|
}
|
||||||
else // we shouldn't send this message. possible leakage
|
else // we shouldn't send this message. possible leakage
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,8 +12,12 @@ namespace tunnel
|
||||||
{
|
{
|
||||||
void TunnelGatewayBuffer::PutI2NPMsg (const TunnelMessageBlock& block)
|
void TunnelGatewayBuffer::PutI2NPMsg (const TunnelMessageBlock& block)
|
||||||
{
|
{
|
||||||
|
bool messageCreated = false;
|
||||||
if (!m_CurrentTunnelDataMsg)
|
if (!m_CurrentTunnelDataMsg)
|
||||||
|
{
|
||||||
CreateCurrentTunnelDataMessage ();
|
CreateCurrentTunnelDataMessage ();
|
||||||
|
messageCreated = true;
|
||||||
|
}
|
||||||
|
|
||||||
// create delivery instructions
|
// create delivery instructions
|
||||||
uint8_t di[43]; // max delivery instruction length is 43 for tunnel
|
uint8_t di[43]; // max delivery instruction length is 43 for tunnel
|
||||||
|
@ -33,7 +37,8 @@ namespace tunnel
|
||||||
|
|
||||||
// create fragments
|
// create fragments
|
||||||
I2NPMessage * msg = block.data;
|
I2NPMessage * msg = block.data;
|
||||||
if (diLen + msg->GetLength () + 2<= m_RemainingSize)
|
auto fullMsgLen = diLen + msg->GetLength () + 2; // delivery instructions + payload + 2 bytes length
|
||||||
|
if (fullMsgLen <= m_RemainingSize)
|
||||||
{
|
{
|
||||||
// message fits. First and last fragment
|
// message fits. First and last fragment
|
||||||
*(uint16_t *)(di + diLen) = htobe16 (msg->GetLength ());
|
*(uint16_t *)(di + diLen) = htobe16 (msg->GetLength ());
|
||||||
|
@ -48,6 +53,18 @@ namespace tunnel
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (!messageCreated) // check if we should complete previous message
|
||||||
|
{
|
||||||
|
auto numFollowOnFragments = fullMsgLen / TUNNEL_DATA_MAX_PAYLOAD_SIZE;
|
||||||
|
// length of bytes don't fit full tunnel message
|
||||||
|
// every follow-on fragment adds 7 bytes
|
||||||
|
auto nonFit = (fullMsgLen + numFollowOnFragments*7) % TUNNEL_DATA_MAX_PAYLOAD_SIZE;
|
||||||
|
if (!nonFit || nonFit > m_RemainingSize)
|
||||||
|
{
|
||||||
|
CompleteCurrentTunnelDataMessage ();
|
||||||
|
CreateCurrentTunnelDataMessage ();
|
||||||
|
}
|
||||||
|
}
|
||||||
if (diLen + 6 <= m_RemainingSize)
|
if (diLen + 6 <= m_RemainingSize)
|
||||||
{
|
{
|
||||||
// delivery instructions fit
|
// delivery instructions fit
|
||||||
|
@ -169,7 +186,7 @@ namespace tunnel
|
||||||
{
|
{
|
||||||
m_Tunnel->EncryptTunnelMsg (tunnelMsg);
|
m_Tunnel->EncryptTunnelMsg (tunnelMsg);
|
||||||
FillI2NPMessageHeader (tunnelMsg, eI2NPTunnelData);
|
FillI2NPMessageHeader (tunnelMsg, eI2NPTunnelData);
|
||||||
i2p::transports.SendMessage (m_Tunnel->GetNextIdentHash (), tunnelMsg);
|
i2p::transport::transports.SendMessage (m_Tunnel->GetNextIdentHash (), tunnelMsg);
|
||||||
m_NumSentBytes += TUNNEL_DATA_MSG_SIZE;
|
m_NumSentBytes += TUNNEL_DATA_MSG_SIZE;
|
||||||
}
|
}
|
||||||
m_Buffer.ClearTunnelDataMsgs ();
|
m_Buffer.ClearTunnelDataMsgs ();
|
||||||
|
|
|
@ -257,7 +257,7 @@ namespace tunnel
|
||||||
{
|
{
|
||||||
// last hop
|
// last hop
|
||||||
auto hop = outboundTunnel->GetTunnelConfig ()->GetFirstHop ()->router;
|
auto hop = outboundTunnel->GetTunnelConfig ()->GetFirstHop ()->router;
|
||||||
if (hop->GetIdentHash () != i2p::context.GetRouterIdentHash ()) // outbound shouldn't be zero-hop tunnel
|
if (hop->GetIdentHash () != i2p::context.GetIdentHash ()) // outbound shouldn't be zero-hop tunnel
|
||||||
{
|
{
|
||||||
prevHop = hop;
|
prevHop = hop;
|
||||||
hops.push_back (prevHop);
|
hops.push_back (prevHop);
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace tunnel
|
||||||
const uint8_t * GetEncryptionPublicKey () const { return m_LocalDestination.GetEncryptionPublicKey (); };
|
const uint8_t * GetEncryptionPublicKey () const { return m_LocalDestination.GetEncryptionPublicKey (); };
|
||||||
const i2p::data::LocalDestination& GetLocalDestination () const { return m_LocalDestination; };
|
const i2p::data::LocalDestination& GetLocalDestination () const { return m_LocalDestination; };
|
||||||
i2p::garlic::GarlicDestination& GetGarlicDestination () const { return m_LocalDestination; };
|
i2p::garlic::GarlicDestination& GetGarlicDestination () const { return m_LocalDestination; };
|
||||||
bool IsExploratory () const { return GetIdentHash () == i2p::context.GetRouterIdentHash (); };
|
bool IsExploratory () const { return GetIdentHash () == i2p::context.GetIdentHash (); };
|
||||||
|
|
||||||
void CreateTunnels ();
|
void CreateTunnels ();
|
||||||
void TunnelCreated (InboundTunnel * createdTunnel);
|
void TunnelCreated (InboundTunnel * createdTunnel);
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
<ClCompile Include="..\SOCKS.cpp" />
|
<ClCompile Include="..\SOCKS.cpp" />
|
||||||
<ClCompile Include="..\I2PTunnel.cpp" />
|
<ClCompile Include="..\I2PTunnel.cpp" />
|
||||||
<ClCompile Include="..\ClientContext.cpp" />
|
<ClCompile Include="..\ClientContext.cpp" />
|
||||||
|
<ClCompile Include="..\Datagram.cpp" />
|
||||||
<ClCompile Include="Win32Service.cpp" />
|
<ClCompile Include="Win32Service.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -91,6 +92,8 @@
|
||||||
<ClInclude Include="..\version.h" />
|
<ClInclude Include="..\version.h" />
|
||||||
<ClInclude Include="..\Signature.h" />
|
<ClInclude Include="..\Signature.h" />
|
||||||
<ClInclude Include="..\ClientContext.h" />
|
<ClInclude Include="..\ClientContext.h" />
|
||||||
|
<ClCompile Include="..\TransportSession.h" />
|
||||||
|
<ClCompile Include="..\Datagram.h" />
|
||||||
<ClInclude Include="Win32Service.h" />
|
<ClInclude Include="Win32Service.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
|
|
|
@ -43,7 +43,8 @@ set (SOURCES
|
||||||
"${CMAKE_SOURCE_DIR}/i2p.cpp"
|
"${CMAKE_SOURCE_DIR}/i2p.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/util.cpp"
|
"${CMAKE_SOURCE_DIR}/util.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/SAM.cpp"
|
"${CMAKE_SOURCE_DIR}/SAM.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/ClientContext.cpp"
|
"${CMAKE_SOURCE_DIR}/ClientContext.cpp"
|
||||||
|
"${CMAKE_SOURCE_DIR}/Datagram.cpp"
|
||||||
)
|
)
|
||||||
|
|
||||||
file (GLOB HEADERS "${CMAKE_SOURCE_DIR}/*.h")
|
file (GLOB HEADERS "${CMAKE_SOURCE_DIR}/*.h")
|
||||||
|
|
|
@ -325,7 +325,7 @@ i2p_SOURCES = AddressBook.cpp CryptoConst.cpp Daemon.cpp \
|
||||||
Transports.cpp Tunnel.cpp TunnelEndpoint.cpp \
|
Transports.cpp Tunnel.cpp TunnelEndpoint.cpp \
|
||||||
TunnelGateway.cpp TunnelPool.cpp UPnP.cpp aes.cpp \
|
TunnelGateway.cpp TunnelPool.cpp UPnP.cpp aes.cpp \
|
||||||
base64.cpp i2p.cpp util.cpp SAM.cpp Destination.cpp \
|
base64.cpp i2p.cpp util.cpp SAM.cpp Destination.cpp \
|
||||||
ClientContext.cpp \
|
ClientContext.cpp DataFram.cpp \
|
||||||
\
|
\
|
||||||
AddressBook.h CryptoConst.h Daemon.h ElGamal.h \
|
AddressBook.h CryptoConst.h Daemon.h ElGamal.h \
|
||||||
Garlic.h HTTPProxy.h HTTPServer.h I2NPProtocol.h \
|
Garlic.h HTTPProxy.h HTTPServer.h I2NPProtocol.h \
|
||||||
|
@ -336,7 +336,8 @@ i2p_SOURCES = AddressBook.cpp CryptoConst.cpp Daemon.cpp \
|
||||||
TransitTunnel.h Transports.h Tunnel.h TunnelBase.h \
|
TransitTunnel.h Transports.h Tunnel.h TunnelBase.h \
|
||||||
TunnelConfig.h TunnelEndpoint.h TunnelGateway.h \
|
TunnelConfig.h TunnelEndpoint.h TunnelGateway.h \
|
||||||
TunnelPool.h UPnP.h aes.h base64.h config.h hmac.h \
|
TunnelPool.h UPnP.h aes.h base64.h config.h hmac.h \
|
||||||
util.h version.h Destination.h ClientContext.h
|
util.h version.h Destination.h ClientContext.h \
|
||||||
|
TransportSession.h Datagram.h
|
||||||
|
|
||||||
AM_LDFLAGS = @BOOST_DATE_TIME_LIB@ @BOOST_FILESYSTEM_LIB@ \
|
AM_LDFLAGS = @BOOST_DATE_TIME_LIB@ @BOOST_FILESYSTEM_LIB@ \
|
||||||
@BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_REGEX_LIB@ \
|
@BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_REGEX_LIB@ \
|
||||||
|
@ -485,6 +486,7 @@ distclean-compile:
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SAM.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SAM.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClientContext.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClientContext.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Datagram.Po@am__quote@
|
||||||
|
|
||||||
.cpp.o:
|
.cpp.o:
|
||||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||||
|
|
22
debian/init.d → debian/i2pd.init
vendored
22
debian/init.d → debian/i2pd.init
vendored
|
@ -57,10 +57,10 @@ do_stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function that sends a SIGHUP to the daemon/service
|
# Function that sends a SIGHUP to the daemon/service
|
||||||
#do_reload() {
|
do_reload() {
|
||||||
# start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
|
start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
|
||||||
# return 0
|
return 0
|
||||||
#}
|
}
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
start)
|
start)
|
||||||
|
@ -82,14 +82,12 @@ case "$1" in
|
||||||
status)
|
status)
|
||||||
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
|
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
|
||||||
;;
|
;;
|
||||||
#reload|force-reload)
|
reload|force-reload)
|
||||||
#log_daemon_msg "Reloading $DESC" "$NAME"
|
log_daemon_msg "Reloading $DESC" "$NAME"
|
||||||
#do_reload
|
do_reload
|
||||||
#log_end_msg $?
|
log_end_msg $?
|
||||||
#;;
|
;;
|
||||||
restart|force-reload)
|
restart)
|
||||||
# If the "reload" option is implemented then remove the
|
|
||||||
# 'force-reload' alias
|
|
||||||
log_daemon_msg "Restarting $DESC" "$NAME"
|
log_daemon_msg "Restarting $DESC" "$NAME"
|
||||||
do_stop
|
do_stop
|
||||||
case "$?" in
|
case "$?" in
|
10
debian/i2pd.upstart
vendored
Normal file
10
debian/i2pd.upstart
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
description "i2p client daemon"
|
||||||
|
|
||||||
|
start on runlevel [2345]
|
||||||
|
stop on runlevel [016] or unmounting-filesystem
|
||||||
|
|
||||||
|
# these can be overridden in /etc/init/i2pd.override
|
||||||
|
env I2P_HOST="1.2.3.4"
|
||||||
|
env I2P_PORT="4567"
|
||||||
|
|
||||||
|
exec /usr/sbin/i2pd --daemon=0 --log=1 --host=$I2P_HOST --port=$I2P_PORT
|
|
@ -5,7 +5,7 @@ CPP_FILES := CryptoConst.cpp base64.cpp NTCPSession.cpp RouterInfo.cpp Transport
|
||||||
TransitTunnel.cpp I2NPProtocol.cpp Log.cpp Garlic.cpp HTTPServer.cpp Streaming.cpp \
|
TransitTunnel.cpp I2NPProtocol.cpp Log.cpp Garlic.cpp HTTPServer.cpp Streaming.cpp \
|
||||||
Destination.cpp Identity.cpp SSU.cpp util.cpp Reseed.cpp DaemonLinux.cpp SSUData.cpp \
|
Destination.cpp Identity.cpp SSU.cpp util.cpp Reseed.cpp DaemonLinux.cpp SSUData.cpp \
|
||||||
aes.cpp SOCKS.cpp UPnP.cpp TunnelPool.cpp HTTPProxy.cpp AddressBook.cpp Daemon.cpp \
|
aes.cpp SOCKS.cpp UPnP.cpp TunnelPool.cpp HTTPProxy.cpp AddressBook.cpp Daemon.cpp \
|
||||||
I2PTunnel.cpp SAM.cpp ClientContext.cpp i2p.cpp
|
I2PTunnel.cpp SAM.cpp ClientContext.cpp Datagram.cpp i2p.cpp
|
||||||
|
|
||||||
|
|
||||||
H_FILES := CryptoConst.h base64.h NTCPSession.h RouterInfo.h Transports.h \
|
H_FILES := CryptoConst.h base64.h NTCPSession.h RouterInfo.h Transports.h \
|
||||||
|
@ -13,7 +13,7 @@ H_FILES := CryptoConst.h base64.h NTCPSession.h RouterInfo.h Transports.h \
|
||||||
TransitTunnel.h I2NPProtocol.h Log.h Garlic.h HTTPServer.h Streaming.h Destination.h \
|
TransitTunnel.h I2NPProtocol.h Log.h Garlic.h HTTPServer.h Streaming.h Destination.h \
|
||||||
Identity.h SSU.h util.h Reseed.h DaemonLinux.h SSUData.h i2p.h aes.h SOCKS.h \
|
Identity.h SSU.h util.h Reseed.h DaemonLinux.h SSUData.h i2p.h aes.h SOCKS.h \
|
||||||
UPnP.h TunnelPool.h HTTPProxy.h AddressBook.h Daemon.h I2PTunnel.h version.h \
|
UPnP.h TunnelPool.h HTTPProxy.h AddressBook.h Daemon.h I2PTunnel.h version.h \
|
||||||
Signature.h SAM.h ClientContext.h
|
Signature.h SAM.h ClientContext.h TransportSession.h Datagram.h
|
||||||
|
|
||||||
|
|
||||||
OBJECTS = $(addprefix obj/, $(notdir $(CPP_FILES:.cpp=.o)))
|
OBJECTS = $(addprefix obj/, $(notdir $(CPP_FILES:.cpp=.o)))
|
||||||
|
|
Loading…
Reference in a new issue