mirror of
https://github.com/PurpleI2P/i2pd
synced 2024-11-10 08:00:38 +03:00
Merge branch 'upstream-master' into http-bind-local
This commit is contained in:
commit
37a5c10c66
@ -295,7 +295,7 @@ namespace client
|
||||
LogPrint (eLogError, "I2P client tunnel with port ", port, " already exists");
|
||||
numClientTunnels++;
|
||||
}
|
||||
else if (type == I2P_TUNNELS_SECTION_TYPE_SERVER)
|
||||
else if (type == I2P_TUNNELS_SECTION_TYPE_SERVER || type == I2P_TUNNELS_SECTION_TYPE_HTTP)
|
||||
{
|
||||
// mandatory params
|
||||
std::string host = section.second.get<std::string> (I2P_SERVER_TUNNEL_HOST);
|
||||
@ -306,7 +306,7 @@ namespace client
|
||||
std::string accessList = section.second.get (I2P_SERVER_TUNNEL_ACCESS_LIST, "");
|
||||
|
||||
auto localDestination = LoadLocalDestination (keys, true);
|
||||
auto serverTunnel = new I2PServerTunnel (host, port, localDestination, inPort);
|
||||
I2PServerTunnel * serverTunnel = (type == I2P_TUNNELS_SECTION_TYPE_HTTP) ? new I2PServerTunnelHTTP (host, port, localDestination, inPort) : new I2PServerTunnel (host, port, localDestination, inPort);
|
||||
if (accessList.length () > 0)
|
||||
{
|
||||
std::set<i2p::data::IdentHash> idents;
|
||||
|
@ -20,6 +20,7 @@ namespace client
|
||||
const char I2P_TUNNELS_SECTION_TYPE[] = "type";
|
||||
const char I2P_TUNNELS_SECTION_TYPE_CLIENT[] = "client";
|
||||
const char I2P_TUNNELS_SECTION_TYPE_SERVER[] = "server";
|
||||
const char I2P_TUNNELS_SECTION_TYPE_HTTP[] = "http";
|
||||
const char I2P_CLIENT_TUNNEL_PORT[] = "port";
|
||||
const char I2P_CLIENT_TUNNEL_DESTINATION[] = "destination";
|
||||
const char I2P_CLIENT_TUNNEL_KEYS[] = "keys";
|
||||
|
@ -62,7 +62,8 @@ namespace i2p
|
||||
LogPrint("Error, could not create process group.");
|
||||
return false;
|
||||
}
|
||||
chdir(i2p::util::filesystem::GetDataDir().string().c_str());
|
||||
std::string d(i2p::util::filesystem::GetDataDir().string ()); // make a copy
|
||||
chdir(d.c_str());
|
||||
|
||||
// close stdin/stdout/stderr descriptors
|
||||
::close (0);
|
||||
|
@ -60,7 +60,7 @@ namespace datagram
|
||||
{
|
||||
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);
|
||||
auto garlic = m_Owner.WrapMessage (remote, ToSharedI2NPMessage (msg), true);
|
||||
msgs.push_back (i2p::tunnel::TunnelMessageBlock
|
||||
{
|
||||
i2p::tunnel::eDeliveryTypeTunnel,
|
||||
@ -143,7 +143,7 @@ namespace datagram
|
||||
htobe16buf (buf + 6, toPort); // destination port
|
||||
buf[9] = i2p::client::PROTOCOL_TYPE_DATAGRAM; // datagram protocol
|
||||
msg->len += size + 4;
|
||||
FillI2NPMessageHeader (msg, eI2NPData);
|
||||
msg->FillI2NPMessageHeader (eI2NPData);
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ namespace client
|
||||
int outboundTunnelLen = DEFAULT_OUTBOUND_TUNNEL_LENGTH;
|
||||
int inboundTunnelsQuantity = DEFAULT_INBOUND_TUNNELS_QUANTITY;
|
||||
int outboundTunnelsQuantity = DEFAULT_OUTBOUND_TUNNELS_QUANTITY;
|
||||
std::shared_ptr<std::vector<i2p::data::IdentHash> > explicitPeers;
|
||||
if (params)
|
||||
{
|
||||
auto it = params->find (I2CP_PARAM_INBOUND_TUNNEL_LENGTH);
|
||||
@ -66,8 +67,24 @@ namespace client
|
||||
LogPrint (eLogInfo, "Outbound tunnels quantity set to ", quantity);
|
||||
}
|
||||
}
|
||||
it = params->find (I2CP_PARAM_EXPLICIT_PEERS);
|
||||
if (it != params->end ())
|
||||
{
|
||||
explicitPeers = std::make_shared<std::vector<i2p::data::IdentHash> >();
|
||||
std::stringstream ss(it->second);
|
||||
std::string b64;
|
||||
while (std::getline (ss, b64, ','))
|
||||
{
|
||||
i2p::data::IdentHash ident;
|
||||
ident.FromBase64 (b64);
|
||||
explicitPeers->push_back (ident);
|
||||
}
|
||||
LogPrint (eLogInfo, "Explicit peers set to ", it->second);
|
||||
}
|
||||
}
|
||||
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (this, inboundTunnelLen, outboundTunnelLen, inboundTunnelsQuantity, outboundTunnelsQuantity);
|
||||
if (explicitPeers)
|
||||
m_Pool->SetExplicitPeers (explicitPeers);
|
||||
if (m_IsPublic)
|
||||
LogPrint (eLogInfo, "Local address ", i2p::client::GetB32Address(GetIdentHash()), " created");
|
||||
m_StreamingDestination = std::make_shared<i2p::stream::StreamingDestination> (*this); // TODO:
|
||||
@ -198,12 +215,12 @@ namespace client
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClientDestination::ProcessGarlicMessage (I2NPMessage * msg)
|
||||
void ClientDestination::ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg)
|
||||
{
|
||||
m_Service.post (std::bind (&ClientDestination::HandleGarlicMessage, this, msg));
|
||||
}
|
||||
|
||||
void ClientDestination::ProcessDeliveryStatusMessage (I2NPMessage * msg)
|
||||
void ClientDestination::ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg)
|
||||
{
|
||||
m_Service.post (std::bind (&ClientDestination::HandleDeliveryStatusMessage, this, msg));
|
||||
}
|
||||
@ -216,6 +233,10 @@ namespace client
|
||||
case eI2NPData:
|
||||
HandleDataMessage (buf + I2NP_HEADER_SIZE, bufbe16toh (buf + I2NP_HEADER_SIZE_OFFSET));
|
||||
break;
|
||||
case eI2NPDeliveryStatus:
|
||||
// we assume tunnel tests non-encrypted
|
||||
HandleDeliveryStatusMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from));
|
||||
break;
|
||||
case eI2NPDatabaseStore:
|
||||
HandleDatabaseStoreMessage (buf + I2NP_HEADER_SIZE, bufbe16toh (buf + I2NP_HEADER_SIZE_OFFSET));
|
||||
break;
|
||||
@ -326,7 +347,7 @@ namespace client
|
||||
LogPrint ("Request for ", key.ToBase64 (), " not found");
|
||||
}
|
||||
|
||||
void ClientDestination::HandleDeliveryStatusMessage (I2NPMessage * msg)
|
||||
void ClientDestination::HandleDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg)
|
||||
{
|
||||
uint32_t msgID = bufbe32toh (msg->GetPayload () + DELIVERY_STATUS_MSGID_OFFSET);
|
||||
if (msgID == m_PublishReplyToken)
|
||||
@ -334,7 +355,6 @@ namespace client
|
||||
LogPrint (eLogDebug, "Publishing confirmed");
|
||||
m_ExcludedFloodfills.clear ();
|
||||
m_PublishReplyToken = 0;
|
||||
i2p::DeleteI2NPMessage (msg);
|
||||
}
|
||||
else
|
||||
i2p::garlic::GarlicDestination::HandleDeliveryStatusMessage (msg);
|
||||
@ -377,7 +397,7 @@ namespace client
|
||||
m_ExcludedFloodfills.insert (floodfill->GetIdentHash ());
|
||||
LogPrint (eLogDebug, "Publish LeaseSet of ", GetIdentHash ().ToBase32 ());
|
||||
m_PublishReplyToken = i2p::context.GetRandomNumberGenerator ().GenerateWord32 ();
|
||||
auto msg = WrapMessage (floodfill, i2p::CreateDatabaseStoreMsg (m_LeaseSet, m_PublishReplyToken));
|
||||
auto msg = WrapMessage (floodfill, ToSharedI2NPMessage (i2p::CreateDatabaseStoreMsg (m_LeaseSet, m_PublishReplyToken)));
|
||||
m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT));
|
||||
m_PublishConfirmationTimer.async_wait (std::bind (&ClientDestination::HandlePublishConfirmationTimer,
|
||||
this, std::placeholders::_1));
|
||||
@ -565,9 +585,9 @@ namespace client
|
||||
rnd.GenerateBlock (replyTag, 32); // random session tag
|
||||
AddSessionKey (replyKey, replyTag);
|
||||
|
||||
I2NPMessage * msg = WrapMessage (nextFloodfill,
|
||||
CreateLeaseSetDatabaseLookupMsg (dest, request->excluded,
|
||||
replyTunnel.get (), replyKey, replyTag));
|
||||
auto msg = WrapMessage (nextFloodfill,
|
||||
ToSharedI2NPMessage (CreateLeaseSetDatabaseLookupMsg (dest, request->excluded,
|
||||
replyTunnel.get (), replyKey, replyTag)));
|
||||
outboundTunnel->SendTunnelDataMsg (
|
||||
{
|
||||
i2p::tunnel::TunnelMessageBlock
|
||||
|
@ -40,6 +40,7 @@ namespace client
|
||||
const int DEFAULT_INBOUND_TUNNELS_QUANTITY = 5;
|
||||
const char I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY[] = "outbound.quantity";
|
||||
const int DEFAULT_OUTBOUND_TUNNELS_QUANTITY = 5;
|
||||
const char I2CP_PARAM_EXPLICIT_PEERS[] = "explicitPeers";
|
||||
const int STREAM_REQUEST_TIMEOUT = 60; //in seconds
|
||||
|
||||
typedef std::function<void (std::shared_ptr<i2p::stream::Stream> stream)> StreamRequestComplete;
|
||||
@ -98,8 +99,8 @@ namespace client
|
||||
|
||||
// override GarlicDestination
|
||||
bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag);
|
||||
void ProcessGarlicMessage (I2NPMessage * msg);
|
||||
void ProcessDeliveryStatusMessage (I2NPMessage * msg);
|
||||
void ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg);
|
||||
void ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
|
||||
void SetLeaseSetUpdated ();
|
||||
|
||||
// I2CP
|
||||
@ -113,7 +114,7 @@ namespace client
|
||||
void HandlePublishConfirmationTimer (const boost::system::error_code& ecode);
|
||||
void HandleDatabaseStoreMessage (const uint8_t * buf, size_t len);
|
||||
void HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len);
|
||||
void HandleDeliveryStatusMessage (I2NPMessage * msg);
|
||||
void HandleDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
|
||||
|
||||
void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete);
|
||||
bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, LeaseSetRequest * request);
|
||||
|
14
ElGamal.h
14
ElGamal.h
@ -60,15 +60,13 @@ namespace crypto
|
||||
{
|
||||
CryptoPP::Integer x(key, 256), a(zeroPadding? encrypted +1 : encrypted, 256),
|
||||
b(zeroPadding? encrypted + 258 :encrypted + 256, 256);
|
||||
uint8_t m[255], hash[32];
|
||||
uint8_t m[255];
|
||||
a_times_b_mod_c (b, a_exp_b_mod_c (a, elgp - x - 1, elgp), elgp).Encode (m, 255);
|
||||
CryptoPP::SHA256().CalculateDigest(hash, m+33, 222);
|
||||
for (int i = 0; i < 32; i++)
|
||||
if (hash[i] != m[i+1])
|
||||
{
|
||||
LogPrint ("ElGamal decrypt hash doesn't match");
|
||||
return false;
|
||||
}
|
||||
if (!CryptoPP::SHA256().VerifyDigest (m + 1, m + 33, 222))
|
||||
{
|
||||
LogPrint ("ElGamal decrypt hash doesn't match");
|
||||
return false;
|
||||
}
|
||||
memcpy (data, m + 33, 222);
|
||||
return true;
|
||||
}
|
||||
|
60
Garlic.cpp
60
Garlic.cpp
@ -107,9 +107,9 @@ namespace garlic
|
||||
return !m_SessionTags.empty () || m_UnconfirmedTagsMsgs.empty ();
|
||||
}
|
||||
|
||||
I2NPMessage * GarlicRoutingSession::WrapSingleMessage (I2NPMessage * msg)
|
||||
std::shared_ptr<I2NPMessage> GarlicRoutingSession::WrapSingleMessage (std::shared_ptr<I2NPMessage> msg)
|
||||
{
|
||||
I2NPMessage * m = NewI2NPMessage ();
|
||||
auto m = ToSharedI2NPMessage(NewI2NPMessage ());
|
||||
m->Align (12); // in order to get buf aligned to 16 (12 + 4)
|
||||
size_t len = 0;
|
||||
uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length
|
||||
@ -164,12 +164,10 @@ namespace garlic
|
||||
len += 32;
|
||||
}
|
||||
// AES block
|
||||
len += CreateAESBlock (buf, msg);
|
||||
len += CreateAESBlock (buf, msg.get ()); // TODO
|
||||
htobe32buf (m->GetPayload (), len);
|
||||
m->len += len + 4;
|
||||
FillI2NPMessageHeader (m, eI2NPGarlic);
|
||||
if (msg)
|
||||
DeleteI2NPMessage (msg);
|
||||
m->FillI2NPMessageHeader (eI2NPGarlic);
|
||||
return m;
|
||||
}
|
||||
|
||||
@ -225,9 +223,10 @@ namespace garlic
|
||||
if (newTags || m_LeaseSetUpdateStatus == eLeaseSetUpdated) // new tags created or leaseset updated
|
||||
{
|
||||
// clove is DeliveryStatus
|
||||
size += CreateDeliveryStatusClove (payload + size, msgID);
|
||||
if (size > 0) // successive?
|
||||
auto cloveSize = CreateDeliveryStatusClove (payload + size, msgID);
|
||||
if (cloveSize > 0) // successive?
|
||||
{
|
||||
size += cloveSize;
|
||||
(*numCloves)++;
|
||||
if (newTags) // new tags created
|
||||
m_UnconfirmedTagsMsgs[msgID] = newTags;
|
||||
@ -308,7 +307,7 @@ namespace garlic
|
||||
htobe32buf (buf + size, inboundTunnel->GetNextTunnelID ()); // tunnelID
|
||||
size += 4;
|
||||
// create msg
|
||||
I2NPMessage * msg = CreateDeliveryStatusMsg (msgID);
|
||||
auto msg = CreateDeliveryStatusMsg (msgID);
|
||||
if (m_Owner)
|
||||
{
|
||||
//encrypt
|
||||
@ -321,7 +320,6 @@ namespace garlic
|
||||
}
|
||||
memcpy (buf + size, msg->GetBuffer (), msg->GetLength ());
|
||||
size += msg->GetLength ();
|
||||
DeleteI2NPMessage (msg);
|
||||
// fill clove
|
||||
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch () + 5000; // 5 sec
|
||||
htobe32buf (buf + size, m_Rnd.GenerateWord32 ()); // CloveID
|
||||
@ -361,27 +359,37 @@ namespace garlic
|
||||
return true;
|
||||
}
|
||||
|
||||
void GarlicDestination::HandleGarlicMessage (I2NPMessage * msg)
|
||||
void GarlicDestination::HandleGarlicMessage (std::shared_ptr<I2NPMessage> msg)
|
||||
{
|
||||
uint8_t * buf = msg->GetPayload ();
|
||||
uint32_t length = bufbe32toh (buf);
|
||||
if (length > msg->GetLength ())
|
||||
{
|
||||
LogPrint (eLogError, "Garlic message length ", length, " exceeds I2NP message length ", msg->GetLength ());
|
||||
return;
|
||||
}
|
||||
buf += 4; // length
|
||||
auto it = m_Tags.find (SessionTag(buf));
|
||||
if (it != m_Tags.end ())
|
||||
{
|
||||
// tag found. Use AES
|
||||
uint8_t iv[32]; // IV is first 16 bytes
|
||||
CryptoPP::SHA256().CalculateDigest(iv, buf, 32);
|
||||
it->second->SetIV (iv);
|
||||
it->second->Decrypt (buf + 32, length - 32, buf + 32);
|
||||
HandleAESBlock (buf + 32, length - 32, it->second, msg->from);
|
||||
m_Tags.erase (it); // tag might be used only once
|
||||
if (length >= 32)
|
||||
{
|
||||
uint8_t iv[32]; // IV is first 16 bytes
|
||||
CryptoPP::SHA256().CalculateDigest(iv, buf, 32);
|
||||
it->second->SetIV (iv);
|
||||
it->second->Decrypt (buf + 32, length - 32, buf + 32);
|
||||
HandleAESBlock (buf + 32, length - 32, it->second, msg->from);
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "Garlic message length ", length, " is less than 32 bytes");
|
||||
m_Tags.erase (it); // tag might be used only once
|
||||
}
|
||||
else
|
||||
{
|
||||
// tag not found. Use ElGamal
|
||||
ElGamalBlock elGamal;
|
||||
if (i2p::crypto::ElGamalDecrypt (GetEncryptionPrivateKey (), buf, (uint8_t *)&elGamal, true))
|
||||
if (length >= 514 && i2p::crypto::ElGamalDecrypt (GetEncryptionPrivateKey (), buf, (uint8_t *)&elGamal, true))
|
||||
{
|
||||
auto decryption = std::make_shared<i2p::crypto::CBCDecryption>();
|
||||
decryption->SetKey (elGamal.sessionKey);
|
||||
@ -392,9 +400,8 @@ namespace garlic
|
||||
HandleAESBlock (buf + 514, length - 514, decryption, msg->from);
|
||||
}
|
||||
else
|
||||
LogPrint ("Failed to decrypt garlic");
|
||||
LogPrint (eLogError, "Failed to decrypt garlic");
|
||||
}
|
||||
DeleteI2NPMessage (msg);
|
||||
|
||||
// cleanup expired tags
|
||||
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
||||
@ -501,7 +508,7 @@ namespace garlic
|
||||
tunnel = from->GetTunnelPool ()->GetNextOutboundTunnel ();
|
||||
if (tunnel) // we have send it through an outbound tunnel
|
||||
{
|
||||
I2NPMessage * msg = CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from);
|
||||
auto msg = CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from);
|
||||
tunnel->SendTunnelDataMsg (gwHash, gwTunnel, msg);
|
||||
}
|
||||
else
|
||||
@ -527,8 +534,8 @@ namespace garlic
|
||||
}
|
||||
}
|
||||
|
||||
I2NPMessage * GarlicDestination::WrapMessage (std::shared_ptr<const i2p::data::RoutingDestination> destination,
|
||||
I2NPMessage * msg, bool attachLeaseSet)
|
||||
std::shared_ptr<I2NPMessage> GarlicDestination::WrapMessage (std::shared_ptr<const i2p::data::RoutingDestination> destination,
|
||||
std::shared_ptr<I2NPMessage> msg, bool attachLeaseSet)
|
||||
{
|
||||
auto session = GetRoutingSession (destination, attachLeaseSet); // 32 tags by default
|
||||
return session->WrapSingleMessage (msg);
|
||||
@ -576,7 +583,7 @@ namespace garlic
|
||||
m_CreatedSessions[msgID] = session;
|
||||
}
|
||||
|
||||
void GarlicDestination::HandleDeliveryStatusMessage (I2NPMessage * msg)
|
||||
void GarlicDestination::HandleDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg)
|
||||
{
|
||||
uint32_t msgID = bufbe32toh (msg->GetPayload ());
|
||||
{
|
||||
@ -588,7 +595,6 @@ namespace garlic
|
||||
LogPrint (eLogInfo, "Garlic message ", msgID, " acknowledged");
|
||||
}
|
||||
}
|
||||
DeleteI2NPMessage (msg);
|
||||
}
|
||||
|
||||
void GarlicDestination::SetLeaseSetUpdated ()
|
||||
@ -598,12 +604,12 @@ namespace garlic
|
||||
it.second->SetLeaseSetUpdated ();
|
||||
}
|
||||
|
||||
void GarlicDestination::ProcessGarlicMessage (I2NPMessage * msg)
|
||||
void GarlicDestination::ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg)
|
||||
{
|
||||
HandleGarlicMessage (msg);
|
||||
}
|
||||
|
||||
void GarlicDestination::ProcessDeliveryStatusMessage (I2NPMessage * msg)
|
||||
void GarlicDestination::ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg)
|
||||
{
|
||||
HandleDeliveryStatusMessage (msg);
|
||||
}
|
||||
|
14
Garlic.h
14
Garlic.h
@ -80,7 +80,7 @@ namespace garlic
|
||||
int numTags, bool attachLeaseSet);
|
||||
GarlicRoutingSession (const uint8_t * sessionKey, const SessionTag& sessionTag); // one time encryption
|
||||
~GarlicRoutingSession ();
|
||||
I2NPMessage * WrapSingleMessage (I2NPMessage * msg);
|
||||
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<I2NPMessage> msg);
|
||||
void MessageConfirmed (uint32_t msgID);
|
||||
bool CleanupExpiredTags (); // returns true if something left
|
||||
|
||||
@ -126,15 +126,15 @@ namespace garlic
|
||||
std::shared_ptr<GarlicRoutingSession> GetRoutingSession (std::shared_ptr<const i2p::data::RoutingDestination> destination, bool attachLeaseSet);
|
||||
void CleanupRoutingSessions ();
|
||||
void RemoveCreatedSession (uint32_t msgID);
|
||||
I2NPMessage * WrapMessage (std::shared_ptr<const i2p::data::RoutingDestination> destination,
|
||||
I2NPMessage * msg, bool attachLeaseSet = false);
|
||||
std::shared_ptr<I2NPMessage> WrapMessage (std::shared_ptr<const i2p::data::RoutingDestination> destination,
|
||||
std::shared_ptr<I2NPMessage> msg, bool attachLeaseSet = false);
|
||||
|
||||
void AddSessionKey (const uint8_t * key, const uint8_t * tag); // one tag
|
||||
virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread
|
||||
void DeliveryStatusSent (std::shared_ptr<GarlicRoutingSession> session, uint32_t msgID);
|
||||
|
||||
virtual void ProcessGarlicMessage (I2NPMessage * msg);
|
||||
virtual void ProcessDeliveryStatusMessage (I2NPMessage * msg);
|
||||
virtual void ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg);
|
||||
virtual void ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
|
||||
virtual void SetLeaseSetUpdated ();
|
||||
|
||||
virtual std::shared_ptr<const i2p::data::LeaseSet> GetLeaseSet () = 0; // TODO
|
||||
@ -143,8 +143,8 @@ namespace garlic
|
||||
|
||||
protected:
|
||||
|
||||
void HandleGarlicMessage (I2NPMessage * msg);
|
||||
void HandleDeliveryStatusMessage (I2NPMessage * msg);
|
||||
void HandleGarlicMessage (std::shared_ptr<I2NPMessage> msg);
|
||||
void HandleDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -90,7 +90,7 @@ namespace proxy
|
||||
//TODO: handle this apropriately
|
||||
void HTTPProxyHandler::HTTPRequestFailed(/*HTTPProxyHandler::errTypes error*/)
|
||||
{
|
||||
std::string response = "HTTP/1.0 500 Internal Server Error\r\nContent-type: text/html\r\nContent-length: 0\r\n";
|
||||
static std::string response = "HTTP/1.0 500 Internal Server Error\r\nContent-type: text/html\r\nContent-length: 0\r\n";
|
||||
boost::asio::async_write(*m_sock, boost::asio::buffer(response,response.size()),
|
||||
std::bind(&HTTPProxyHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1));
|
||||
}
|
||||
|
132
I2NPProtocol.cpp
132
I2NPProtocol.cpp
@ -41,30 +41,22 @@ namespace i2p
|
||||
return std::shared_ptr<I2NPMessage>(msg, DeleteI2NPMessage);
|
||||
}
|
||||
|
||||
static std::atomic<uint32_t> I2NPmsgID(0); // TODO: create class
|
||||
void FillI2NPMessageHeader (I2NPMessage * msg, I2NPMessageType msgType, uint32_t replyMsgID)
|
||||
void I2NPMessage::FillI2NPMessageHeader (I2NPMessageType msgType, uint32_t replyMsgID)
|
||||
{
|
||||
msg->SetTypeID (msgType);
|
||||
SetTypeID (msgType);
|
||||
if (replyMsgID) // for tunnel creation
|
||||
msg->SetMsgID (replyMsgID);
|
||||
else
|
||||
{
|
||||
msg->SetMsgID (I2NPmsgID);
|
||||
I2NPmsgID++;
|
||||
}
|
||||
msg->SetExpiration (i2p::util::GetMillisecondsSinceEpoch () + 5000); // TODO: 5 secs is a magic number
|
||||
msg->UpdateSize ();
|
||||
msg->UpdateChks ();
|
||||
SetMsgID (replyMsgID);
|
||||
else
|
||||
SetMsgID (i2p::context.GetRandomNumberGenerator ().GenerateWord32 ());
|
||||
SetExpiration (i2p::util::GetMillisecondsSinceEpoch () + 5000); // TODO: 5 secs is a magic number
|
||||
UpdateSize ();
|
||||
UpdateChks ();
|
||||
}
|
||||
|
||||
void RenewI2NPMessageHeader (I2NPMessage * msg)
|
||||
void I2NPMessage::RenewI2NPMessageHeader ()
|
||||
{
|
||||
if (msg)
|
||||
{
|
||||
msg->SetMsgID (I2NPmsgID);
|
||||
I2NPmsgID++;
|
||||
msg->SetExpiration (i2p::util::GetMillisecondsSinceEpoch () + 5000);
|
||||
}
|
||||
SetMsgID (i2p::context.GetRandomNumberGenerator ().GenerateWord32 ());
|
||||
SetExpiration (i2p::util::GetMillisecondsSinceEpoch () + 5000);
|
||||
}
|
||||
|
||||
I2NPMessage * CreateI2NPMessage (I2NPMessageType msgType, const uint8_t * buf, int len, uint32_t replyMsgID)
|
||||
@ -77,11 +69,11 @@ namespace i2p
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "I2NP message length ", len, " exceeds max length");
|
||||
FillI2NPMessageHeader (msg, msgType, replyMsgID);
|
||||
msg->FillI2NPMessageHeader (msgType, replyMsgID);
|
||||
return msg;
|
||||
}
|
||||
|
||||
I2NPMessage * CreateI2NPMessage (const uint8_t * buf, int len, std::shared_ptr<i2p::tunnel::InboundTunnel> from)
|
||||
std::shared_ptr<I2NPMessage> CreateI2NPMessage (const uint8_t * buf, int len, std::shared_ptr<i2p::tunnel::InboundTunnel> from)
|
||||
{
|
||||
I2NPMessage * msg = NewI2NPMessage ();
|
||||
if (msg->offset + len < msg->maxLen)
|
||||
@ -92,10 +84,10 @@ namespace i2p
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "I2NP message length ", len, " exceeds max length");
|
||||
return msg;
|
||||
return ToSharedI2NPMessage(msg);
|
||||
}
|
||||
|
||||
I2NPMessage * CreateDeliveryStatusMsg (uint32_t msgID)
|
||||
std::shared_ptr<I2NPMessage> CreateDeliveryStatusMsg (uint32_t msgID)
|
||||
{
|
||||
I2NPMessage * m = NewI2NPShortMessage ();
|
||||
uint8_t * buf = m->GetPayload ();
|
||||
@ -110,14 +102,14 @@ namespace i2p
|
||||
htobe64buf (buf + DELIVERY_STATUS_TIMESTAMP_OFFSET, 2); // netID = 2
|
||||
}
|
||||
m->len += DELIVERY_STATUS_SIZE;
|
||||
FillI2NPMessageHeader (m, eI2NPDeliveryStatus);
|
||||
return m;
|
||||
m->FillI2NPMessageHeader (eI2NPDeliveryStatus);
|
||||
return ToSharedI2NPMessage (m);
|
||||
}
|
||||
|
||||
I2NPMessage * CreateRouterInfoDatabaseLookupMsg (const uint8_t * key, const uint8_t * from,
|
||||
uint32_t replyTunnelID, bool exploratory, std::set<i2p::data::IdentHash> * excludedPeers)
|
||||
{
|
||||
I2NPMessage * m = NewI2NPShortMessage ();
|
||||
I2NPMessage * m = excludedPeers ? NewI2NPMessage () : NewI2NPShortMessage ();
|
||||
uint8_t * buf = m->GetPayload ();
|
||||
memcpy (buf, key, 32); // key
|
||||
buf += 32;
|
||||
@ -155,7 +147,7 @@ namespace i2p
|
||||
}
|
||||
|
||||
m->len += (buf - m->GetPayload ());
|
||||
FillI2NPMessageHeader (m, eI2NPDatabaseLookup);
|
||||
m->FillI2NPMessageHeader (eI2NPDatabaseLookup);
|
||||
return m;
|
||||
}
|
||||
|
||||
@ -163,7 +155,8 @@ namespace i2p
|
||||
const std::set<i2p::data::IdentHash>& excludedFloodfills,
|
||||
const i2p::tunnel::InboundTunnel * replyTunnel, const uint8_t * replyKey, const uint8_t * replyTag)
|
||||
{
|
||||
I2NPMessage * m = NewI2NPShortMessage ();
|
||||
int cnt = excludedFloodfills.size ();
|
||||
I2NPMessage * m = cnt > 0 ? NewI2NPMessage () : NewI2NPShortMessage ();
|
||||
uint8_t * buf = m->GetPayload ();
|
||||
memcpy (buf, dest, 32); // key
|
||||
buf += 32;
|
||||
@ -174,7 +167,6 @@ namespace i2p
|
||||
buf += 5;
|
||||
|
||||
// excluded
|
||||
int cnt = excludedFloodfills.size ();
|
||||
htobe16buf (buf, cnt);
|
||||
buf += 2;
|
||||
if (cnt > 0)
|
||||
@ -192,11 +184,9 @@ namespace i2p
|
||||
buf += 65;
|
||||
|
||||
m->len += (buf - m->GetPayload ());
|
||||
FillI2NPMessageHeader (m, eI2NPDatabaseLookup);
|
||||
m->FillI2NPMessageHeader (eI2NPDatabaseLookup);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
I2NPMessage * CreateDatabaseSearchReply (const i2p::data::IdentHash& ident,
|
||||
std::vector<i2p::data::IdentHash> routers)
|
||||
@ -216,7 +206,7 @@ namespace i2p
|
||||
memcpy (buf + len, i2p::context.GetRouterInfo ().GetIdentHash (), 32);
|
||||
len += 32;
|
||||
m->len += len;
|
||||
FillI2NPMessageHeader (m, eI2NPDatabaseSearchReply);
|
||||
m->FillI2NPMessageHeader (eI2NPDatabaseSearchReply);
|
||||
return m;
|
||||
}
|
||||
|
||||
@ -246,11 +236,19 @@ namespace i2p
|
||||
auto size = compressor.MaxRetrievable ();
|
||||
htobe16buf (buf, size); // size
|
||||
buf += 2;
|
||||
// TODO: check if size doesn't exceed buffer
|
||||
compressor.Get (buf, size);
|
||||
buf += size;
|
||||
m->len += (buf - payload); // payload size
|
||||
FillI2NPMessageHeader (m, eI2NPDatabaseStore);
|
||||
if (m->len + size > m->maxLen)
|
||||
{
|
||||
LogPrint (eLogInfo, "DatabaseStore message size is not enough for ", m->len + size);
|
||||
auto newMsg = NewI2NPMessage ();
|
||||
*newMsg = *m;
|
||||
DeleteI2NPMessage (m);
|
||||
m = newMsg;
|
||||
buf = m->buf + m->len;
|
||||
}
|
||||
compressor.Get (buf, size);
|
||||
m->len += size;
|
||||
m->FillI2NPMessageHeader (eI2NPDatabaseStore);
|
||||
|
||||
return m;
|
||||
}
|
||||
@ -280,7 +278,7 @@ namespace i2p
|
||||
memcpy (payload + size, leaseSet->GetBuffer (), leaseSet->GetBufferLen ());
|
||||
size += leaseSet->GetBufferLen ();
|
||||
m->len += size;
|
||||
FillI2NPMessageHeader (m, eI2NPDatabaseStore);
|
||||
m->FillI2NPMessageHeader (eI2NPDatabaseStore);
|
||||
return m;
|
||||
}
|
||||
|
||||
@ -363,14 +361,14 @@ namespace i2p
|
||||
{
|
||||
// so we send it to reply tunnel
|
||||
transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
|
||||
CreateTunnelGatewayMsg (bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
|
||||
ToSharedI2NPMessage (CreateTunnelGatewayMsg (bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
|
||||
eI2NPVariableTunnelBuildReply, buf, len,
|
||||
bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
|
||||
bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET))));
|
||||
}
|
||||
else
|
||||
transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
|
||||
CreateI2NPMessage (eI2NPVariableTunnelBuild, buf, len,
|
||||
bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
|
||||
ToSharedI2NPMessage (CreateI2NPMessage (eI2NPVariableTunnelBuild, buf, len,
|
||||
bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET))));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -384,14 +382,14 @@ namespace i2p
|
||||
{
|
||||
// so we send it to reply tunnel
|
||||
transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
|
||||
CreateTunnelGatewayMsg (bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
|
||||
ToSharedI2NPMessage (CreateTunnelGatewayMsg (bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
|
||||
eI2NPTunnelBuildReply, buf, len,
|
||||
bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
|
||||
bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET))));
|
||||
}
|
||||
else
|
||||
transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
|
||||
CreateI2NPMessage (eI2NPTunnelBuild, buf, len,
|
||||
bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
|
||||
ToSharedI2NPMessage (CreateI2NPMessage (eI2NPTunnelBuild, buf, len,
|
||||
bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET))));
|
||||
}
|
||||
}
|
||||
|
||||
@ -424,7 +422,7 @@ namespace i2p
|
||||
I2NPMessage * msg = NewI2NPShortMessage ();
|
||||
memcpy (msg->GetPayload (), buf, i2p::tunnel::TUNNEL_DATA_MSG_SIZE);
|
||||
msg->len += i2p::tunnel::TUNNEL_DATA_MSG_SIZE;
|
||||
FillI2NPMessageHeader (msg, eI2NPTunnelData);
|
||||
msg->FillI2NPMessageHeader (eI2NPTunnelData);
|
||||
return msg;
|
||||
}
|
||||
|
||||
@ -434,9 +432,16 @@ namespace i2p
|
||||
memcpy (msg->GetPayload () + 4, payload, i2p::tunnel::TUNNEL_DATA_MSG_SIZE - 4);
|
||||
htobe32buf (msg->GetPayload (), tunnelID);
|
||||
msg->len += i2p::tunnel::TUNNEL_DATA_MSG_SIZE;
|
||||
FillI2NPMessageHeader (msg, eI2NPTunnelData);
|
||||
msg->FillI2NPMessageHeader (eI2NPTunnelData);
|
||||
return msg;
|
||||
}
|
||||
|
||||
std::shared_ptr<I2NPMessage> CreateEmptyTunnelDataMsg ()
|
||||
{
|
||||
I2NPMessage * msg = NewI2NPShortMessage ();
|
||||
msg->len += i2p::tunnel::TUNNEL_DATA_MSG_SIZE;
|
||||
return ToSharedI2NPMessage (msg);
|
||||
}
|
||||
|
||||
I2NPMessage * CreateTunnelGatewayMsg (uint32_t tunnelID, const uint8_t * buf, size_t len)
|
||||
{
|
||||
@ -446,11 +451,11 @@ namespace i2p
|
||||
htobe16buf (payload + TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET, len);
|
||||
memcpy (payload + TUNNEL_GATEWAY_HEADER_SIZE, buf, len);
|
||||
msg->len += TUNNEL_GATEWAY_HEADER_SIZE + len;
|
||||
FillI2NPMessageHeader (msg, eI2NPTunnelGateway);
|
||||
msg->FillI2NPMessageHeader (eI2NPTunnelGateway);
|
||||
return msg;
|
||||
}
|
||||
|
||||
I2NPMessage * CreateTunnelGatewayMsg (uint32_t tunnelID, I2NPMessage * msg)
|
||||
std::shared_ptr<I2NPMessage> CreateTunnelGatewayMsg (uint32_t tunnelID, std::shared_ptr<I2NPMessage> msg)
|
||||
{
|
||||
if (msg->offset >= I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE)
|
||||
{
|
||||
@ -461,14 +466,13 @@ namespace i2p
|
||||
htobe16buf (payload + TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET, len);
|
||||
msg->offset -= (I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE);
|
||||
msg->len = msg->offset + I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE +len;
|
||||
FillI2NPMessageHeader (msg, eI2NPTunnelGateway);
|
||||
msg->FillI2NPMessageHeader (eI2NPTunnelGateway);
|
||||
return msg;
|
||||
}
|
||||
else
|
||||
{
|
||||
I2NPMessage * msg1 = CreateTunnelGatewayMsg (tunnelID, msg->GetBuffer (), msg->GetLength ());
|
||||
DeleteI2NPMessage (msg);
|
||||
return msg1;
|
||||
return ToSharedI2NPMessage (msg1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -481,13 +485,13 @@ namespace i2p
|
||||
msg->len += gatewayMsgOffset;
|
||||
memcpy (msg->GetPayload (), buf, len);
|
||||
msg->len += len;
|
||||
FillI2NPMessageHeader (msg, msgType, replyMsgID); // create content message
|
||||
msg->FillI2NPMessageHeader (msgType, replyMsgID); // create content message
|
||||
len = msg->GetLength ();
|
||||
msg->offset -= gatewayMsgOffset;
|
||||
uint8_t * payload = msg->GetPayload ();
|
||||
htobe32buf (payload + TUNNEL_GATEWAY_HEADER_TUNNELID_OFFSET, tunnelID);
|
||||
htobe16buf (payload + TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET, len);
|
||||
FillI2NPMessageHeader (msg, eI2NPTunnelGateway); // gateway message
|
||||
msg->FillI2NPMessageHeader (eI2NPTunnelGateway); // gateway message
|
||||
return msg;
|
||||
}
|
||||
|
||||
@ -527,7 +531,7 @@ namespace i2p
|
||||
}
|
||||
}
|
||||
|
||||
void HandleI2NPMessage (I2NPMessage * msg)
|
||||
void HandleI2NPMessage (std::shared_ptr<I2NPMessage> msg)
|
||||
{
|
||||
if (msg)
|
||||
{
|
||||
@ -542,20 +546,19 @@ namespace i2p
|
||||
i2p::tunnel::tunnels.PostTunnelData (msg);
|
||||
break;
|
||||
case eI2NPGarlic:
|
||||
{
|
||||
LogPrint ("Garlic");
|
||||
if (msg->from)
|
||||
{
|
||||
if (msg->from->GetTunnelPool ())
|
||||
msg->from->GetTunnelPool ()->ProcessGarlicMessage (msg);
|
||||
else
|
||||
{
|
||||
LogPrint (eLogInfo, "Local destination for garlic doesn't exist anymore");
|
||||
DeleteI2NPMessage (msg);
|
||||
}
|
||||
}
|
||||
else
|
||||
i2p::context.ProcessGarlicMessage (msg);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case eI2NPDatabaseStore:
|
||||
case eI2NPDatabaseSearchReply:
|
||||
case eI2NPDatabaseLookup:
|
||||
@ -563,12 +566,14 @@ namespace i2p
|
||||
i2p::data::netdb.PostI2NPMsg (msg);
|
||||
break;
|
||||
case eI2NPDeliveryStatus:
|
||||
{
|
||||
LogPrint ("DeliveryStatus");
|
||||
if (msg->from && msg->from->GetTunnelPool ())
|
||||
msg->from->GetTunnelPool ()->ProcessDeliveryStatus (msg);
|
||||
else
|
||||
i2p::context.ProcessDeliveryStatusMessage (msg);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case eI2NPVariableTunnelBuild:
|
||||
case eI2NPVariableTunnelBuildReply:
|
||||
case eI2NPTunnelBuild:
|
||||
@ -578,7 +583,6 @@ namespace i2p
|
||||
break;
|
||||
default:
|
||||
HandleI2NPMessage (msg->GetBuffer (), msg->GetLength ());
|
||||
DeleteI2NPMessage (msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -588,7 +592,7 @@ namespace i2p
|
||||
Flush ();
|
||||
}
|
||||
|
||||
void I2NPMessagesHandler::PutNextMessage (I2NPMessage * msg)
|
||||
void I2NPMessagesHandler::PutNextMessage (std::shared_ptr<I2NPMessage> msg)
|
||||
{
|
||||
if (msg)
|
||||
{
|
||||
|
@ -138,6 +138,7 @@ namespace tunnel
|
||||
|
||||
// payload
|
||||
uint8_t * GetPayload () { return GetBuffer () + I2NP_HEADER_SIZE; };
|
||||
const uint8_t * GetPayload () const { return GetBuffer () + I2NP_HEADER_SIZE; };
|
||||
uint8_t * GetBuffer () { return buf + offset; };
|
||||
const uint8_t * GetBuffer () const { return buf + offset; };
|
||||
size_t GetLength () const { return len - offset; };
|
||||
@ -183,6 +184,9 @@ namespace tunnel
|
||||
len = offset + I2NP_SHORT_HEADER_SIZE + bufbe16toh (header + I2NP_HEADER_SIZE_OFFSET);
|
||||
return bufbe32toh (header + I2NP_HEADER_MSGID_OFFSET);
|
||||
}
|
||||
|
||||
void FillI2NPMessageHeader (I2NPMessageType msgType, uint32_t replyMsgID = 0);
|
||||
void RenewI2NPMessageHeader ();
|
||||
};
|
||||
|
||||
template<int sz>
|
||||
@ -198,12 +202,10 @@ namespace tunnel
|
||||
void DeleteI2NPMessage (I2NPMessage * msg);
|
||||
std::shared_ptr<I2NPMessage> ToSharedI2NPMessage (I2NPMessage * msg);
|
||||
|
||||
void FillI2NPMessageHeader (I2NPMessage * msg, I2NPMessageType msgType, uint32_t replyMsgID = 0);
|
||||
void RenewI2NPMessageHeader (I2NPMessage * msg);
|
||||
I2NPMessage * CreateI2NPMessage (I2NPMessageType msgType, const uint8_t * buf, int len, uint32_t replyMsgID = 0);
|
||||
I2NPMessage * CreateI2NPMessage (const uint8_t * buf, int len, std::shared_ptr<i2p::tunnel::InboundTunnel> from = nullptr);
|
||||
std::shared_ptr<I2NPMessage> CreateI2NPMessage (const uint8_t * buf, int len, std::shared_ptr<i2p::tunnel::InboundTunnel> from = nullptr);
|
||||
|
||||
I2NPMessage * CreateDeliveryStatusMsg (uint32_t msgID);
|
||||
std::shared_ptr<I2NPMessage> CreateDeliveryStatusMsg (uint32_t msgID);
|
||||
I2NPMessage * CreateRouterInfoDatabaseLookupMsg (const uint8_t * key, const uint8_t * from,
|
||||
uint32_t replyTunnelID, bool exploratory = false, std::set<i2p::data::IdentHash> * excludedPeers = nullptr);
|
||||
I2NPMessage * CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest,
|
||||
@ -221,27 +223,28 @@ namespace tunnel
|
||||
|
||||
I2NPMessage * CreateTunnelDataMsg (const uint8_t * buf);
|
||||
I2NPMessage * CreateTunnelDataMsg (uint32_t tunnelID, const uint8_t * payload);
|
||||
std::shared_ptr<I2NPMessage> CreateEmptyTunnelDataMsg ();
|
||||
|
||||
I2NPMessage * CreateTunnelGatewayMsg (uint32_t tunnelID, const uint8_t * buf, size_t len);
|
||||
I2NPMessage * CreateTunnelGatewayMsg (uint32_t tunnelID, I2NPMessageType msgType,
|
||||
const uint8_t * buf, size_t len, uint32_t replyMsgID = 0);
|
||||
I2NPMessage * CreateTunnelGatewayMsg (uint32_t tunnelID, I2NPMessage * msg);
|
||||
std::shared_ptr<I2NPMessage> CreateTunnelGatewayMsg (uint32_t tunnelID, std::shared_ptr<I2NPMessage> msg);
|
||||
|
||||
size_t GetI2NPMessageLength (const uint8_t * msg);
|
||||
void HandleI2NPMessage (uint8_t * msg, size_t len);
|
||||
void HandleI2NPMessage (I2NPMessage * msg);
|
||||
void HandleI2NPMessage (std::shared_ptr<I2NPMessage> msg);
|
||||
|
||||
class I2NPMessagesHandler
|
||||
{
|
||||
public:
|
||||
|
||||
~I2NPMessagesHandler ();
|
||||
void PutNextMessage (I2NPMessage * msg);
|
||||
void PutNextMessage (std::shared_ptr<I2NPMessage> msg);
|
||||
void Flush ();
|
||||
|
||||
private:
|
||||
|
||||
std::vector<I2NPMessage *> m_TunnelMsgs, m_TunnelGatewayMsgs;
|
||||
std::vector<std::shared_ptr<I2NPMessage> > m_TunnelMsgs, m_TunnelGatewayMsgs;
|
||||
};
|
||||
}
|
||||
|
||||
|
107
I2PTunnel.cpp
107
I2PTunnel.cpp
@ -129,10 +129,13 @@ namespace client
|
||||
Terminate ();
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::asio::async_write (*m_Socket, boost::asio::buffer (m_StreamBuffer, bytes_transferred),
|
||||
std::bind (&I2PTunnelConnection::HandleWrite, shared_from_this (), std::placeholders::_1));
|
||||
}
|
||||
Write (m_StreamBuffer, bytes_transferred);
|
||||
}
|
||||
|
||||
void I2PTunnelConnection::Write (const uint8_t * buf, size_t len)
|
||||
{
|
||||
m_Socket->async_send (boost::asio::buffer (buf, len),
|
||||
std::bind (&I2PTunnelConnection::HandleWrite, shared_from_this (), std::placeholders::_1));
|
||||
}
|
||||
|
||||
void I2PTunnelConnection::HandleConnect (const boost::system::error_code& ecode)
|
||||
@ -159,6 +162,47 @@ namespace client
|
||||
}
|
||||
}
|
||||
|
||||
I2PTunnelConnectionHTTP::I2PTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
|
||||
std::shared_ptr<boost::asio::ip::tcp::socket> socket,
|
||||
const boost::asio::ip::tcp::endpoint& target, const std::string& host):
|
||||
I2PTunnelConnection (owner, stream, socket, target), m_Host (host), m_HeaderSent (false)
|
||||
{
|
||||
}
|
||||
|
||||
void I2PTunnelConnectionHTTP::Write (const uint8_t * buf, size_t len)
|
||||
{
|
||||
if (m_HeaderSent)
|
||||
I2PTunnelConnection::Write (buf, len);
|
||||
else
|
||||
{
|
||||
m_InHeader.clear ();
|
||||
m_InHeader.write ((const char *)buf, len);
|
||||
std::string line;
|
||||
bool endOfHeader = false;
|
||||
while (!endOfHeader)
|
||||
{
|
||||
std::getline(m_InHeader, line);
|
||||
if (!m_InHeader.fail ())
|
||||
{
|
||||
if (line.find ("Host:") != std::string::npos)
|
||||
m_OutHeader << "Host: " << m_Host << "\r\n";
|
||||
else
|
||||
m_OutHeader << line << "\n";
|
||||
if (line == "\r") endOfHeader = true;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (endOfHeader)
|
||||
{
|
||||
m_OutHeader << m_InHeader.str (); // data right after header
|
||||
m_HeaderSent = true;
|
||||
I2PTunnelConnection::Write ((uint8_t *)m_OutHeader.str ().c_str (), m_OutHeader.str ().length ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This handler tries to stablish a connection with the desired server and dies if it fails to do so */
|
||||
class I2PClientTunnelHandler: public I2PServiceHandler, public std::enable_shared_from_this<I2PClientTunnelHandler>
|
||||
{
|
||||
@ -255,14 +299,28 @@ namespace client
|
||||
|
||||
I2PServerTunnel::I2PServerTunnel (const std::string& address, int port,
|
||||
std::shared_ptr<ClientDestination> localDestination, int inport):
|
||||
I2PService (localDestination), m_Endpoint (boost::asio::ip::address::from_string (address), port), m_IsAccessList (false)
|
||||
I2PService (localDestination), m_Address (address), m_Port (port), m_IsAccessList (false)
|
||||
{
|
||||
m_PortDestination = localDestination->CreateStreamingDestination (inport > 0 ? inport : port);
|
||||
}
|
||||
|
||||
void I2PServerTunnel::Start ()
|
||||
{
|
||||
Accept ();
|
||||
m_Endpoint.port (m_Port);
|
||||
boost::system::error_code ec;
|
||||
auto addr = boost::asio::ip::address::from_string (m_Address, ec);
|
||||
if (!ec)
|
||||
{
|
||||
m_Endpoint.address (addr);
|
||||
Accept ();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto resolver = std::make_shared<boost::asio::ip::tcp::resolver>(GetService ());
|
||||
resolver->async_resolve (boost::asio::ip::tcp::resolver::query (m_Address, ""),
|
||||
std::bind (&I2PServerTunnel::HandleResolve, this,
|
||||
std::placeholders::_1, std::placeholders::_2, resolver));
|
||||
}
|
||||
}
|
||||
|
||||
void I2PServerTunnel::Stop ()
|
||||
@ -270,6 +328,20 @@ namespace client
|
||||
ClearHandlers ();
|
||||
}
|
||||
|
||||
void I2PServerTunnel::HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it,
|
||||
std::shared_ptr<boost::asio::ip::tcp::resolver> resolver)
|
||||
{
|
||||
if (!ecode)
|
||||
{
|
||||
auto addr = (*it).endpoint ().address ();
|
||||
LogPrint (eLogInfo, "server tunnel ", (*it).host_name (), " has been resolved to ", addr);
|
||||
m_Endpoint.address (addr);
|
||||
Accept ();
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "Unable to resolve server tunnel address: ", ecode.message ());
|
||||
}
|
||||
|
||||
void I2PServerTunnel::SetAccessList (const std::set<i2p::data::IdentHash>& accessList)
|
||||
{
|
||||
m_AccessList = accessList;
|
||||
@ -304,10 +376,27 @@ namespace client
|
||||
return;
|
||||
}
|
||||
}
|
||||
auto conn = std::make_shared<I2PTunnelConnection> (this, stream, std::make_shared<boost::asio::ip::tcp::socket> (GetService ()), m_Endpoint);
|
||||
AddHandler (conn);
|
||||
conn->Connect ();
|
||||
CreateI2PConnection (stream);
|
||||
}
|
||||
}
|
||||
|
||||
void I2PServerTunnel::CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream)
|
||||
{
|
||||
auto conn = std::make_shared<I2PTunnelConnection> (this, stream, std::make_shared<boost::asio::ip::tcp::socket> (GetService ()), GetEndpoint ());
|
||||
AddHandler (conn);
|
||||
conn->Connect ();
|
||||
}
|
||||
|
||||
I2PServerTunnelHTTP::I2PServerTunnelHTTP (const std::string& address, int port, std::shared_ptr<ClientDestination> localDestination, int inport):
|
||||
I2PServerTunnel (address, port, localDestination, inport)
|
||||
{
|
||||
}
|
||||
|
||||
void I2PServerTunnelHTTP::CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream)
|
||||
{
|
||||
auto conn = std::make_shared<I2PTunnelConnectionHTTP> (this, stream, std::make_shared<boost::asio::ip::tcp::socket> (GetService ()), GetEndpoint (), GetAddress ());
|
||||
AddHandler (conn);
|
||||
conn->Connect ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
47
I2PTunnel.h
47
I2PTunnel.h
@ -5,6 +5,7 @@
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <boost/asio.hpp>
|
||||
#include "Identity.h"
|
||||
#include "Destination.h"
|
||||
@ -27,19 +28,20 @@ namespace client
|
||||
I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
|
||||
std::shared_ptr<const i2p::data::LeaseSet> leaseSet, int port = 0); // to I2P
|
||||
I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
|
||||
std::shared_ptr<i2p::stream::Stream> stream); // to I2P using simplified API :)
|
||||
std::shared_ptr<i2p::stream::Stream> stream); // to I2P using simplified API
|
||||
I2PTunnelConnection (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
|
||||
const boost::asio::ip::tcp::endpoint& target, bool quiet = true); // from I2P
|
||||
~I2PTunnelConnection ();
|
||||
void I2PConnect (const uint8_t * msg = nullptr, size_t len = 0);
|
||||
void Connect ();
|
||||
|
||||
private:
|
||||
protected:
|
||||
|
||||
void Terminate ();
|
||||
|
||||
void Receive ();
|
||||
void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||
virtual void Write (const uint8_t * buf, size_t len); // can be overloaded
|
||||
void HandleWrite (const boost::system::error_code& ecode);
|
||||
|
||||
void StreamReceive ();
|
||||
@ -55,6 +57,25 @@ namespace client
|
||||
bool m_IsQuiet; // don't send destination
|
||||
};
|
||||
|
||||
class I2PTunnelConnectionHTTP: public I2PTunnelConnection
|
||||
{
|
||||
public:
|
||||
|
||||
I2PTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
|
||||
std::shared_ptr<boost::asio::ip::tcp::socket> socket,
|
||||
const boost::asio::ip::tcp::endpoint& target, const std::string& host);
|
||||
|
||||
protected:
|
||||
|
||||
void Write (const uint8_t * buf, size_t len);
|
||||
|
||||
private:
|
||||
|
||||
std::string m_Host;
|
||||
std::stringstream m_InHeader, m_OutHeader;
|
||||
bool m_HeaderSent;
|
||||
};
|
||||
|
||||
class I2PClientTunnel: public TCPIPAcceptor
|
||||
{
|
||||
protected:
|
||||
@ -92,18 +113,40 @@ namespace client
|
||||
|
||||
void SetAccessList (const std::set<i2p::data::IdentHash>& accessList);
|
||||
|
||||
const std::string& GetAddress() const { return m_Address; }
|
||||
int GetPort () const { return m_Port; };
|
||||
const boost::asio::ip::tcp::endpoint& GetEndpoint () const { return m_Endpoint; }
|
||||
|
||||
private:
|
||||
|
||||
void HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it,
|
||||
std::shared_ptr<boost::asio::ip::tcp::resolver> resolver);
|
||||
|
||||
void Accept ();
|
||||
void HandleAccept (std::shared_ptr<i2p::stream::Stream> stream);
|
||||
virtual void CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream);
|
||||
|
||||
private:
|
||||
|
||||
std::string m_Address;
|
||||
int m_Port;
|
||||
boost::asio::ip::tcp::endpoint m_Endpoint;
|
||||
std::shared_ptr<i2p::stream::StreamingDestination> m_PortDestination;
|
||||
std::set<i2p::data::IdentHash> m_AccessList;
|
||||
bool m_IsAccessList;
|
||||
};
|
||||
|
||||
class I2PServerTunnelHTTP: public I2PServerTunnel
|
||||
{
|
||||
public:
|
||||
|
||||
I2PServerTunnelHTTP (const std::string& address, int port,
|
||||
std::shared_ptr<ClientDestination> localDestination, int inport = 0);
|
||||
|
||||
private:
|
||||
|
||||
void CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,6 +69,11 @@ namespace data
|
||||
i2p::data::Base32ToByteStream (s.c_str (), s.length (), m_Buf, sz);
|
||||
}
|
||||
|
||||
void FromBase64 (const std::string& s)
|
||||
{
|
||||
i2p::data::Base64ToByteStream (s.c_str (), s.length (), m_Buf, sz);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
union // 8 bytes alignment
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <stdlib.h>
|
||||
#include "I2PEndian.h"
|
||||
#include <cryptopp/dh.h>
|
||||
#include <cryptopp/adler32.h>
|
||||
#include "base64.h"
|
||||
#include "Log.h"
|
||||
#include "Timestamp.h"
|
||||
@ -82,14 +83,8 @@ namespace transport
|
||||
m_Socket.close ();
|
||||
transports.PeerDisconnected (shared_from_this ());
|
||||
m_Server.RemoveNTCPSession (shared_from_this ());
|
||||
for (auto it: m_SendQueue)
|
||||
DeleteI2NPMessage (it);
|
||||
m_SendQueue.clear ();
|
||||
if (m_NextMessage)
|
||||
{
|
||||
i2p::DeleteI2NPMessage (m_NextMessage);
|
||||
m_NextMessage = nullptr;
|
||||
}
|
||||
m_NextMessage = nullptr;
|
||||
m_TerminationTimer.cancel ();
|
||||
LogPrint (eLogInfo, "NTCP session terminated");
|
||||
}
|
||||
@ -106,7 +101,7 @@ namespace transport
|
||||
m_DHKeysPair = nullptr;
|
||||
|
||||
SendTimeSyncMessage ();
|
||||
PostI2NPMessage (CreateDatabaseStoreMsg ()); // we tell immediately who we are
|
||||
m_SendQueue.push_back (ToSharedI2NPMessage(CreateDatabaseStoreMsg ())); // we tell immediately who we are
|
||||
|
||||
transports.PeerConnected (shared_from_this ());
|
||||
}
|
||||
@ -565,7 +560,8 @@ namespace transport
|
||||
LogPrint (eLogError, "NTCP data size ", dataSize, " exceeds max size");
|
||||
return false;
|
||||
}
|
||||
m_NextMessage = dataSize <= I2NP_MAX_SHORT_MESSAGE_SIZE - 2 ? NewI2NPShortMessage () : NewI2NPMessage ();
|
||||
auto msg = dataSize <= I2NP_MAX_SHORT_MESSAGE_SIZE - 2 ? NewI2NPShortMessage () : NewI2NPMessage ();
|
||||
m_NextMessage = ToSharedI2NPMessage (msg);
|
||||
memcpy (m_NextMessage->buf, buf, 16);
|
||||
m_NextMessageOffset = 16;
|
||||
m_NextMessage->offset = 2; // size field
|
||||
@ -587,20 +583,23 @@ namespace transport
|
||||
if (m_NextMessageOffset >= m_NextMessage->len + 4) // +checksum
|
||||
{
|
||||
// we have a complete I2NP message
|
||||
m_Handler.PutNextMessage (m_NextMessage);
|
||||
if (CryptoPP::Adler32().VerifyDigest (m_NextMessage->buf + m_NextMessageOffset - 4, m_NextMessage->buf, m_NextMessageOffset - 4))
|
||||
m_Handler.PutNextMessage (m_NextMessage);
|
||||
else
|
||||
LogPrint (eLogWarning, "Incorrect adler checksum of NTCP message. Dropped");
|
||||
m_NextMessage = nullptr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void NTCPSession::Send (i2p::I2NPMessage * msg)
|
||||
void NTCPSession::Send (std::shared_ptr<i2p::I2NPMessage> msg)
|
||||
{
|
||||
m_IsSending = true;
|
||||
boost::asio::async_write (m_Socket, CreateMsgBuffer (msg), boost::asio::transfer_all (),
|
||||
std::bind(&NTCPSession::HandleSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2, std::vector<I2NPMessage *>{ msg }));
|
||||
std::bind(&NTCPSession::HandleSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2, std::vector<std::shared_ptr<I2NPMessage> >{ msg }));
|
||||
}
|
||||
|
||||
boost::asio::const_buffers_1 NTCPSession::CreateMsgBuffer (I2NPMessage * msg)
|
||||
boost::asio::const_buffers_1 NTCPSession::CreateMsgBuffer (std::shared_ptr<I2NPMessage> msg)
|
||||
{
|
||||
uint8_t * sendBuffer;
|
||||
int len;
|
||||
@ -609,10 +608,7 @@ namespace transport
|
||||
{
|
||||
// regular I2NP
|
||||
if (msg->offset < 2)
|
||||
{
|
||||
LogPrint (eLogError, "Malformed I2NP message");
|
||||
i2p::DeleteI2NPMessage (msg);
|
||||
}
|
||||
LogPrint (eLogError, "Malformed I2NP message"); // TODO:
|
||||
sendBuffer = msg->GetBuffer () - 2;
|
||||
len = msg->GetLength ();
|
||||
htobe16buf (sendBuffer, len);
|
||||
@ -629,7 +625,7 @@ namespace transport
|
||||
int padding = 0;
|
||||
if (rem > 0) padding = 16 - rem;
|
||||
// TODO: fill padding
|
||||
m_Adler.CalculateDigest (sendBuffer + len + 2 + padding, sendBuffer, len + 2+ padding);
|
||||
CryptoPP::Adler32().CalculateDigest (sendBuffer + len + 2 + padding, sendBuffer, len + 2+ padding);
|
||||
|
||||
int l = len + padding + 6;
|
||||
m_Encryption.Encrypt(sendBuffer, l, sendBuffer);
|
||||
@ -637,7 +633,7 @@ namespace transport
|
||||
}
|
||||
|
||||
|
||||
void NTCPSession::Send (const std::vector<I2NPMessage *>& msgs)
|
||||
void NTCPSession::Send (const std::vector<std::shared_ptr<I2NPMessage> >& msgs)
|
||||
{
|
||||
m_IsSending = true;
|
||||
std::vector<boost::asio::const_buffer> bufs;
|
||||
@ -647,11 +643,9 @@ namespace transport
|
||||
std::bind(&NTCPSession::HandleSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2, msgs));
|
||||
}
|
||||
|
||||
void NTCPSession::HandleSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, std::vector<I2NPMessage *> msgs)
|
||||
void NTCPSession::HandleSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, std::vector<std::shared_ptr<I2NPMessage> > msgs)
|
||||
{
|
||||
m_IsSending = false;
|
||||
for (auto it: msgs)
|
||||
if (it) i2p::DeleteI2NPMessage (it);
|
||||
if (ecode)
|
||||
{
|
||||
LogPrint (eLogWarning, "Couldn't send msgs: ", ecode.message ());
|
||||
@ -679,40 +673,15 @@ namespace transport
|
||||
Send (nullptr);
|
||||
}
|
||||
|
||||
void NTCPSession::SendI2NPMessage (I2NPMessage * msg)
|
||||
{
|
||||
m_Server.GetService ().post (std::bind (&NTCPSession::PostI2NPMessage, shared_from_this (), msg));
|
||||
}
|
||||
|
||||
void NTCPSession::PostI2NPMessage (I2NPMessage * msg)
|
||||
{
|
||||
if (msg)
|
||||
{
|
||||
if (m_IsTerminated)
|
||||
{
|
||||
DeleteI2NPMessage (msg);
|
||||
return;
|
||||
}
|
||||
if (m_IsSending)
|
||||
m_SendQueue.push_back (msg);
|
||||
else
|
||||
Send (msg);
|
||||
}
|
||||
}
|
||||
|
||||
void NTCPSession::SendI2NPMessages (const std::vector<I2NPMessage *>& msgs)
|
||||
void NTCPSession::SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs)
|
||||
{
|
||||
m_Server.GetService ().post (std::bind (&NTCPSession::PostI2NPMessages, shared_from_this (), msgs));
|
||||
}
|
||||
|
||||
void NTCPSession::PostI2NPMessages (std::vector<I2NPMessage *> msgs)
|
||||
void NTCPSession::PostI2NPMessages (std::vector<std::shared_ptr<I2NPMessage> > msgs)
|
||||
{
|
||||
if (m_IsTerminated)
|
||||
{
|
||||
for (auto it: msgs)
|
||||
DeleteI2NPMessage (it);
|
||||
return;
|
||||
}
|
||||
if (m_IsTerminated) return;
|
||||
if (m_IsSending)
|
||||
{
|
||||
for (auto it: msgs)
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include <boost/asio.hpp>
|
||||
#include <cryptopp/modes.h>
|
||||
#include <cryptopp/aes.h>
|
||||
#include <cryptopp/adler32.h>
|
||||
#include "aes.h"
|
||||
#include "Identity.h"
|
||||
#include "RouterInfo.h"
|
||||
@ -62,13 +61,11 @@ namespace transport
|
||||
|
||||
void ClientLogin ();
|
||||
void ServerLogin ();
|
||||
void SendI2NPMessage (I2NPMessage * msg);
|
||||
void SendI2NPMessages (const std::vector<I2NPMessage *>& msgs);
|
||||
void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
|
||||
|
||||
private:
|
||||
|
||||
void PostI2NPMessage (I2NPMessage * msg);
|
||||
void PostI2NPMessages (std::vector<I2NPMessage *> msgs);
|
||||
void PostI2NPMessages (std::vector<std::shared_ptr<I2NPMessage> > msgs);
|
||||
void Connected ();
|
||||
void SendTimeSyncMessage ();
|
||||
void SetIsEstablished (bool isEstablished) { m_IsEstablished = isEstablished; }
|
||||
@ -97,10 +94,10 @@ namespace transport
|
||||
void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||
bool DecryptNextBlock (const uint8_t * encrypted);
|
||||
|
||||
void Send (i2p::I2NPMessage * msg);
|
||||
boost::asio::const_buffers_1 CreateMsgBuffer (I2NPMessage * msg);
|
||||
void Send (const std::vector<I2NPMessage *>& msgs);
|
||||
void HandleSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, std::vector<I2NPMessage *> msgs);
|
||||
void Send (std::shared_ptr<i2p::I2NPMessage> msg);
|
||||
boost::asio::const_buffers_1 CreateMsgBuffer (std::shared_ptr<I2NPMessage> msg);
|
||||
void Send (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
|
||||
void HandleSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, std::vector<std::shared_ptr<I2NPMessage> > msgs);
|
||||
|
||||
|
||||
// timer
|
||||
@ -116,7 +113,6 @@ namespace transport
|
||||
|
||||
i2p::crypto::CBCDecryption m_Decryption;
|
||||
i2p::crypto::CBCEncryption m_Encryption;
|
||||
CryptoPP::Adler32 m_Adler;
|
||||
|
||||
struct Establisher
|
||||
{
|
||||
@ -128,12 +124,12 @@ namespace transport
|
||||
i2p::crypto::AESAlignedBuffer<16> m_TimeSyncBuffer;
|
||||
int m_ReceiveBufferOffset;
|
||||
|
||||
i2p::I2NPMessage * m_NextMessage;
|
||||
std::shared_ptr<I2NPMessage> m_NextMessage;
|
||||
size_t m_NextMessageOffset;
|
||||
i2p::I2NPMessagesHandler m_Handler;
|
||||
|
||||
bool m_IsSending;
|
||||
std::vector<I2NPMessage *> m_SendQueue;
|
||||
std::vector<std::shared_ptr<I2NPMessage> > m_SendQueue;
|
||||
|
||||
boost::asio::ip::address m_ConnectedFrom; // for ban
|
||||
};
|
||||
|
146
NetDb.cpp
146
NetDb.cpp
@ -21,11 +21,7 @@ namespace i2p
|
||||
{
|
||||
namespace data
|
||||
{
|
||||
#ifndef _WIN32
|
||||
const char NetDb::m_NetDbPath[] = "/netDb";
|
||||
#else
|
||||
const char NetDb::m_NetDbPath[] = "\\netDb";
|
||||
#endif
|
||||
const char NetDb::m_NetDbPath[] = "netDb";
|
||||
NetDb netdb;
|
||||
|
||||
NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr)
|
||||
@ -40,7 +36,7 @@ namespace data
|
||||
|
||||
void NetDb::Start ()
|
||||
{
|
||||
Load (m_NetDbPath);
|
||||
Load ();
|
||||
if (m_RouterInfos.size () < 25) // reseed if # of router less than 50
|
||||
{
|
||||
// try SU3 first
|
||||
@ -55,7 +51,7 @@ namespace data
|
||||
{
|
||||
m_Reseeder->reseedNow();
|
||||
reseedRetries++;
|
||||
Load (m_NetDbPath);
|
||||
Load ();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -92,7 +88,7 @@ namespace data
|
||||
{
|
||||
try
|
||||
{
|
||||
I2NPMessage * msg = m_Queue.GetNextWithTimeout (15000); // 15 sec
|
||||
auto msg = m_Queue.GetNextWithTimeout (15000); // 15 sec
|
||||
if (msg)
|
||||
{
|
||||
int numMsgs = 0;
|
||||
@ -102,19 +98,19 @@ namespace data
|
||||
{
|
||||
case eI2NPDatabaseStore:
|
||||
LogPrint ("DatabaseStore");
|
||||
HandleDatabaseStoreMsg (ToSharedI2NPMessage (msg));
|
||||
HandleDatabaseStoreMsg (msg);
|
||||
break;
|
||||
case eI2NPDatabaseSearchReply:
|
||||
LogPrint ("DatabaseSearchReply");
|
||||
HandleDatabaseSearchReplyMsg (ToSharedI2NPMessage (msg));
|
||||
HandleDatabaseSearchReplyMsg (msg);
|
||||
break;
|
||||
case eI2NPDatabaseLookup:
|
||||
LogPrint ("DatabaseLookup");
|
||||
HandleDatabaseLookupMsg (ToSharedI2NPMessage (msg));
|
||||
HandleDatabaseLookupMsg (msg);
|
||||
break;
|
||||
default: // WTF?
|
||||
LogPrint (eLogError, "NetDb: unexpected message type ", msg->GetTypeID ());
|
||||
i2p::HandleI2NPMessage (msg);
|
||||
//i2p::HandleI2NPMessage (msg);
|
||||
}
|
||||
if (numMsgs > 100) break;
|
||||
msg = m_Queue.Get ();
|
||||
@ -133,7 +129,7 @@ namespace data
|
||||
{
|
||||
if (lastSave)
|
||||
{
|
||||
SaveUpdated (m_NetDbPath);
|
||||
SaveUpdated ();
|
||||
ManageLeaseSets ();
|
||||
}
|
||||
lastSave = ts;
|
||||
@ -295,10 +291,9 @@ namespace data
|
||||
LogPrint (eLogWarning, "Failed to reseed after 10 attempts");
|
||||
}
|
||||
|
||||
void NetDb::Load (const char * directory)
|
||||
void NetDb::Load ()
|
||||
{
|
||||
boost::filesystem::path p (i2p::util::filesystem::GetDataDir());
|
||||
p /= (directory);
|
||||
boost::filesystem::path p(i2p::util::filesystem::GetDataDir() / m_NetDbPath);
|
||||
if (!boost::filesystem::exists (p))
|
||||
{
|
||||
// seems netDb doesn't exist yet
|
||||
@ -345,27 +340,15 @@ namespace data
|
||||
LogPrint (m_Floodfills.size (), " floodfills loaded");
|
||||
}
|
||||
|
||||
void NetDb::SaveUpdated (const char * directory)
|
||||
void NetDb::SaveUpdated ()
|
||||
{
|
||||
auto GetFilePath = [](const char * directory, const RouterInfo * routerInfo)
|
||||
auto GetFilePath = [](const boost::filesystem::path& directory, const RouterInfo * routerInfo)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
return std::string (directory) + "/r" +
|
||||
routerInfo->GetIdentHashBase64 ()[0] + "/routerInfo-" +
|
||||
#else
|
||||
return std::string (directory) + "\\r" +
|
||||
routerInfo->GetIdentHashBase64 ()[0] + "\\routerInfo-" +
|
||||
#endif
|
||||
routerInfo->GetIdentHashBase64 () + ".dat";
|
||||
std::string s(routerInfo->GetIdentHashBase64());
|
||||
return directory / (std::string("r") + s[0]) / ("routerInfo-" + s + ".dat");
|
||||
};
|
||||
|
||||
boost::filesystem::path p (i2p::util::filesystem::GetDataDir());
|
||||
p /= (directory);
|
||||
#if BOOST_VERSION > 10500
|
||||
const char * fullDirectory = p.string().c_str ();
|
||||
#else
|
||||
const char * fullDirectory = p.c_str ();
|
||||
#endif
|
||||
boost::filesystem::path fullDirectory (i2p::util::filesystem::GetDataDir() / m_NetDbPath);
|
||||
int count = 0, deletedCount = 0;
|
||||
auto total = m_RouterInfos.size ();
|
||||
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch ();
|
||||
@ -373,7 +356,8 @@ namespace data
|
||||
{
|
||||
if (it.second->IsUpdated ())
|
||||
{
|
||||
it.second->SaveToFile (GetFilePath(fullDirectory, it.second.get ()));
|
||||
std::string f = GetFilePath(fullDirectory, it.second.get()).string();
|
||||
it.second->SaveToFile (f);
|
||||
it.second->SetUpdated (false);
|
||||
it.second->SetUnreachable (false);
|
||||
it.second->DeleteBuffer ();
|
||||
@ -469,7 +453,7 @@ namespace data
|
||||
}
|
||||
}
|
||||
|
||||
void NetDb::HandleDatabaseStoreMsg (std::shared_ptr<I2NPMessage> m)
|
||||
void NetDb::HandleDatabaseStoreMsg (std::shared_ptr<const I2NPMessage> m)
|
||||
{
|
||||
const uint8_t * buf = m->GetPayload ();
|
||||
size_t len = m->GetSize ();
|
||||
@ -495,32 +479,26 @@ namespace data
|
||||
if (outbound)
|
||||
outbound->SendTunnelDataMsg (buf + offset, tunnelID, deliveryStatus);
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "No outbound tunnels for DatabaseStore reply found");
|
||||
DeleteI2NPMessage (deliveryStatus);
|
||||
}
|
||||
}
|
||||
offset += 32;
|
||||
|
||||
if (context.IsFloodfill ())
|
||||
{
|
||||
// flood it
|
||||
auto floodMsg = ToSharedI2NPMessage (NewI2NPShortMessage ());
|
||||
uint8_t * payload = floodMsg->GetPayload ();
|
||||
memcpy (payload, buf, 33); // key + type
|
||||
htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0); // zero reply token
|
||||
memcpy (payload + DATABASE_STORE_HEADER_SIZE, buf + offset, len - offset);
|
||||
floodMsg->len += DATABASE_STORE_HEADER_SIZE + len -offset;
|
||||
floodMsg->FillI2NPMessageHeader (eI2NPDatabaseStore);
|
||||
std::set<IdentHash> excluded;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
auto floodfill = GetClosestFloodfill (ident, excluded);
|
||||
if (floodfill)
|
||||
{
|
||||
excluded.insert (floodfill->GetIdentHash ());
|
||||
auto floodMsg = NewI2NPShortMessage ();
|
||||
uint8_t * payload = floodMsg->GetPayload ();
|
||||
memcpy (payload, buf, 33); // key + type
|
||||
htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0); // zero reply token
|
||||
memcpy (payload + DATABASE_STORE_HEADER_SIZE, buf + offset, len - offset);
|
||||
floodMsg->len += DATABASE_STORE_HEADER_SIZE + len -offset;
|
||||
FillI2NPMessageHeader (floodMsg, eI2NPDatabaseStore);
|
||||
transports.SendMessage (floodfill->GetIdentHash (), floodMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -562,9 +540,9 @@ namespace data
|
||||
}
|
||||
}
|
||||
|
||||
void NetDb::HandleDatabaseSearchReplyMsg (std::shared_ptr<I2NPMessage> msg)
|
||||
void NetDb::HandleDatabaseSearchReplyMsg (std::shared_ptr<const I2NPMessage> msg)
|
||||
{
|
||||
uint8_t * buf = msg->GetPayload ();
|
||||
const uint8_t * buf = msg->GetPayload ();
|
||||
char key[48];
|
||||
int l = i2p::data::ByteStreamToBase64 (buf, 32, key, 48);
|
||||
key[l] = 0;
|
||||
@ -597,7 +575,7 @@ namespace data
|
||||
{
|
||||
i2p::tunnel::eDeliveryTypeRouter,
|
||||
nextFloodfill->GetIdentHash (), 0,
|
||||
CreateDatabaseStoreMsg ()
|
||||
ToSharedI2NPMessage (CreateDatabaseStoreMsg ())
|
||||
});
|
||||
|
||||
// request destination
|
||||
@ -633,7 +611,7 @@ namespace data
|
||||
// try responses
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
uint8_t * router = buf + 33 + i*32;
|
||||
const uint8_t * router = buf + 33 + i*32;
|
||||
char peerHash[48];
|
||||
int l1 = i2p::data::ByteStreamToBase64 (router, 32, peerHash, 48);
|
||||
peerHash[l1] = 0;
|
||||
@ -651,9 +629,9 @@ namespace data
|
||||
}
|
||||
}
|
||||
|
||||
void NetDb::HandleDatabaseLookupMsg (std::shared_ptr<I2NPMessage> msg)
|
||||
void NetDb::HandleDatabaseLookupMsg (std::shared_ptr<const I2NPMessage> msg)
|
||||
{
|
||||
uint8_t * buf = msg->GetPayload ();
|
||||
const uint8_t * buf = msg->GetPayload ();
|
||||
IdentHash ident (buf);
|
||||
if (ident.IsZero ())
|
||||
{
|
||||
@ -666,7 +644,7 @@ namespace data
|
||||
uint8_t flag = buf[64];
|
||||
LogPrint ("DatabaseLookup for ", key, " recieved flags=", (int)flag);
|
||||
uint8_t lookupType = flag & DATABASE_LOOKUP_TYPE_FLAGS_MASK;
|
||||
uint8_t * excluded = buf + 65;
|
||||
const uint8_t * excluded = buf + 65;
|
||||
uint32_t replyTunnelID = 0;
|
||||
if (flag & DATABASE_LOOKUP_DELIVERY_FLAG) //reply to tunnel
|
||||
{
|
||||
@ -681,7 +659,7 @@ namespace data
|
||||
numExcluded = 0; // TODO:
|
||||
}
|
||||
|
||||
I2NPMessage * replyMsg = nullptr;
|
||||
std::shared_ptr<I2NPMessage> replyMsg;
|
||||
if (lookupType == DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP)
|
||||
{
|
||||
LogPrint ("Exploratory close to ", key, " ", numExcluded, " excluded");
|
||||
@ -701,7 +679,7 @@ namespace data
|
||||
excludedRouters.insert (r->GetIdentHash ());
|
||||
}
|
||||
}
|
||||
replyMsg = CreateDatabaseSearchReply (ident, routers);
|
||||
replyMsg = ToSharedI2NPMessage (CreateDatabaseSearchReply (ident, routers));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -714,7 +692,7 @@ namespace data
|
||||
LogPrint ("Requested RouterInfo ", key, " found");
|
||||
router->LoadBuffer ();
|
||||
if (router->GetBuffer ())
|
||||
replyMsg = CreateDatabaseStoreMsg (router);
|
||||
replyMsg = ToSharedI2NPMessage (CreateDatabaseStoreMsg (router));
|
||||
}
|
||||
}
|
||||
|
||||
@ -725,35 +703,20 @@ namespace data
|
||||
if (leaseSet) // we don't send back our LeaseSets
|
||||
{
|
||||
LogPrint ("Requested LeaseSet ", key, " found");
|
||||
replyMsg = CreateDatabaseStoreMsg (leaseSet);
|
||||
replyMsg = ToSharedI2NPMessage (CreateDatabaseStoreMsg (leaseSet));
|
||||
}
|
||||
}
|
||||
|
||||
if (!replyMsg)
|
||||
{
|
||||
LogPrint ("Requested ", key, " not found. ", numExcluded, " excluded");
|
||||
std::vector<IdentHash> routers;
|
||||
if (numExcluded > 0)
|
||||
{
|
||||
std::set<IdentHash> excludedRouters;
|
||||
for (int i = 0; i < numExcluded; i++)
|
||||
{
|
||||
excludedRouters.insert (excluded);
|
||||
excluded += 32;
|
||||
}
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
auto floodfill = GetClosestFloodfill (ident, excludedRouters);
|
||||
if (floodfill)
|
||||
{
|
||||
routers.push_back (floodfill->GetIdentHash ());
|
||||
excludedRouters.insert (floodfill->GetIdentHash ());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
routers = GetClosestFloodfills (ident, 3);
|
||||
replyMsg = CreateDatabaseSearchReply (ident, routers);
|
||||
std::set<IdentHash> excludedRouters;
|
||||
for (int i = 0; i < numExcluded; i++)
|
||||
{
|
||||
excludedRouters.insert (excluded);
|
||||
excluded += 32;
|
||||
}
|
||||
replyMsg = ToSharedI2NPMessage (CreateDatabaseSearchReply (ident, GetClosestFloodfills (ident, 3, excludedRouters)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -764,11 +727,11 @@ namespace data
|
||||
// encryption might be used though tunnel only
|
||||
if (flag & DATABASE_LOOKUP_ENCYPTION_FLAG) // encrypted reply requested
|
||||
{
|
||||
uint8_t * sessionKey = excluded;
|
||||
const uint8_t * sessionKey = excluded;
|
||||
uint8_t numTags = sessionKey[32];
|
||||
if (numTags > 0)
|
||||
{
|
||||
uint8_t * sessionTag = sessionKey + 33; // take first tag
|
||||
const uint8_t * sessionTag = sessionKey + 33; // take first tag
|
||||
i2p::garlic::GarlicRoutingSession garlic (sessionKey, sessionTag);
|
||||
replyMsg = garlic.WrapSingleMessage (replyMsg);
|
||||
}
|
||||
@ -819,7 +782,7 @@ namespace data
|
||||
{
|
||||
i2p::tunnel::eDeliveryTypeRouter,
|
||||
floodfill->GetIdentHash (), 0,
|
||||
CreateDatabaseStoreMsg () // tell floodfill about us
|
||||
ToSharedI2NPMessage (CreateDatabaseStoreMsg ()) // tell floodfill about us
|
||||
});
|
||||
msgs.push_back (i2p::tunnel::TunnelMessageBlock
|
||||
{
|
||||
@ -848,7 +811,7 @@ namespace data
|
||||
{
|
||||
uint32_t replyToken = i2p::context.GetRandomNumberGenerator ().GenerateWord32 ();
|
||||
LogPrint ("Publishing our RouterInfo to ", floodfill->GetIdentHashAbbreviation (), ". reply token=", replyToken);
|
||||
transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken));
|
||||
transports.SendMessage (floodfill->GetIdentHash (), ToSharedI2NPMessage (CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken)));
|
||||
excluded.insert (floodfill->GetIdentHash ());
|
||||
}
|
||||
}
|
||||
@ -927,7 +890,7 @@ namespace data
|
||||
return nullptr; // seems we have too few routers
|
||||
}
|
||||
|
||||
void NetDb::PostI2NPMsg (I2NPMessage * msg)
|
||||
void NetDb::PostI2NPMsg (std::shared_ptr<const I2NPMessage> msg)
|
||||
{
|
||||
if (msg) m_Queue.Put (msg);
|
||||
}
|
||||
@ -955,7 +918,8 @@ namespace data
|
||||
return r;
|
||||
}
|
||||
|
||||
std::vector<IdentHash> NetDb::GetClosestFloodfills (const IdentHash& destination, size_t num) const
|
||||
std::vector<IdentHash> NetDb::GetClosestFloodfills (const IdentHash& destination, size_t num,
|
||||
std::set<IdentHash>& excluded) const
|
||||
{
|
||||
struct Sorted
|
||||
{
|
||||
@ -990,8 +954,12 @@ namespace data
|
||||
{
|
||||
if (i < num)
|
||||
{
|
||||
res.push_back (it.r->GetIdentHash ());
|
||||
i++;
|
||||
auto& ident = it.r->GetIdentHash ();
|
||||
if (!excluded.count (ident))
|
||||
{
|
||||
res.push_back (ident);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
17
NetDb.h
17
NetDb.h
@ -41,9 +41,9 @@ namespace data
|
||||
|
||||
void RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete = nullptr);
|
||||
|
||||
void HandleDatabaseStoreMsg (std::shared_ptr<I2NPMessage> msg);
|
||||
void HandleDatabaseSearchReplyMsg (std::shared_ptr<I2NPMessage> msg);
|
||||
void HandleDatabaseLookupMsg (std::shared_ptr<I2NPMessage> msg);
|
||||
void HandleDatabaseStoreMsg (std::shared_ptr<const I2NPMessage> msg);
|
||||
void HandleDatabaseSearchReplyMsg (std::shared_ptr<const I2NPMessage> msg);
|
||||
void HandleDatabaseLookupMsg (std::shared_ptr<const I2NPMessage> msg);
|
||||
|
||||
std::shared_ptr<const RouterInfo> GetRandomRouter () const;
|
||||
std::shared_ptr<const RouterInfo> GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith) const;
|
||||
@ -51,11 +51,12 @@ namespace data
|
||||
std::shared_ptr<const RouterInfo> GetRandomPeerTestRouter () const;
|
||||
std::shared_ptr<const RouterInfo> GetRandomIntroducer () const;
|
||||
std::shared_ptr<const RouterInfo> GetClosestFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const;
|
||||
std::vector<IdentHash> GetClosestFloodfills (const IdentHash& destination, size_t num) const;
|
||||
std::vector<IdentHash> GetClosestFloodfills (const IdentHash& destination, size_t num,
|
||||
std::set<IdentHash>& excluded) const;
|
||||
std::shared_ptr<const RouterInfo> GetClosestNonFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const;
|
||||
void SetUnreachable (const IdentHash& ident, bool unreachable);
|
||||
|
||||
void PostI2NPMsg (I2NPMessage * msg);
|
||||
void PostI2NPMsg (std::shared_ptr<const I2NPMessage> msg);
|
||||
|
||||
void Reseed ();
|
||||
|
||||
@ -67,8 +68,8 @@ namespace data
|
||||
private:
|
||||
|
||||
bool CreateNetDb(boost::filesystem::path directory);
|
||||
void Load (const char * directory);
|
||||
void SaveUpdated (const char * directory);
|
||||
void Load ();
|
||||
void SaveUpdated ();
|
||||
void Run (); // exploratory thread
|
||||
void Explore (int numDestinations);
|
||||
void Publish ();
|
||||
@ -88,7 +89,7 @@ namespace data
|
||||
|
||||
bool m_IsRunning;
|
||||
std::thread * m_Thread;
|
||||
i2p::util::Queue<I2NPMessage> m_Queue; // of I2NPDatabaseStoreMsg
|
||||
i2p::util::Queue<std::shared_ptr<const I2NPMessage> > m_Queue; // of I2NPDatabaseStoreMsg
|
||||
|
||||
Reseeder * m_Reseeder;
|
||||
|
||||
|
@ -8,7 +8,7 @@ namespace i2p
|
||||
{
|
||||
namespace data
|
||||
{
|
||||
I2NPMessage * RequestedDestination::CreateRequestMessage (std::shared_ptr<const RouterInfo> router,
|
||||
std::shared_ptr<I2NPMessage> RequestedDestination::CreateRequestMessage (std::shared_ptr<const RouterInfo> router,
|
||||
std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel)
|
||||
{
|
||||
I2NPMessage * msg = i2p::CreateRouterInfoDatabaseLookupMsg (m_Destination,
|
||||
@ -16,16 +16,16 @@ namespace data
|
||||
&m_ExcludedPeers);
|
||||
m_ExcludedPeers.insert (router->GetIdentHash ());
|
||||
m_CreationTime = i2p::util::GetSecondsSinceEpoch ();
|
||||
return msg;
|
||||
return ToSharedI2NPMessage (msg);
|
||||
}
|
||||
|
||||
I2NPMessage * RequestedDestination::CreateRequestMessage (const IdentHash& floodfill)
|
||||
std::shared_ptr<I2NPMessage> RequestedDestination::CreateRequestMessage (const IdentHash& floodfill)
|
||||
{
|
||||
I2NPMessage * msg = i2p::CreateRouterInfoDatabaseLookupMsg (m_Destination,
|
||||
i2p::context.GetRouterInfo ().GetIdentHash () , 0, false, &m_ExcludedPeers);
|
||||
m_ExcludedPeers.insert (floodfill);
|
||||
m_CreationTime = i2p::util::GetSecondsSinceEpoch ();
|
||||
return msg;
|
||||
return ToSharedI2NPMessage (msg);
|
||||
}
|
||||
|
||||
void RequestedDestination::ClearExcludedPeers ()
|
||||
|
@ -28,8 +28,8 @@ namespace data
|
||||
bool IsExploratory () const { return m_IsExploratory; };
|
||||
bool IsExcluded (const IdentHash& ident) const { return m_ExcludedPeers.count (ident); };
|
||||
uint64_t GetCreationTime () const { return m_CreationTime; };
|
||||
I2NPMessage * CreateRequestMessage (std::shared_ptr<const RouterInfo>, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel);
|
||||
I2NPMessage * CreateRequestMessage (const IdentHash& floodfill);
|
||||
std::shared_ptr<I2NPMessage> CreateRequestMessage (std::shared_ptr<const RouterInfo>, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel);
|
||||
std::shared_ptr<I2NPMessage> CreateRequestMessage (const IdentHash& floodfill);
|
||||
|
||||
void SetRequestComplete (const RequestComplete& requestComplete) { m_RequestComplete = requestComplete; };
|
||||
bool IsRequestComplete () const { return m_RequestComplete != nullptr; };
|
||||
|
@ -11,8 +11,8 @@ namespace data
|
||||
{
|
||||
RouterProfile::RouterProfile (const IdentHash& identHash):
|
||||
m_IdentHash (identHash), m_LastUpdateTime (boost::posix_time::second_clock::local_time()),
|
||||
m_NumTunnelsAgreed (0), m_NumTunnelsDeclined (0),
|
||||
m_NumTunnelsNonReplied (0)
|
||||
m_NumTunnelsAgreed (0), m_NumTunnelsDeclined (0), m_NumTunnelsNonReplied (0),
|
||||
m_NumTimesTaken (0), m_NumTimesRejected (0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -33,11 +33,15 @@ namespace data
|
||||
participation.put (PEER_PROFILE_PARTICIPATION_AGREED, m_NumTunnelsAgreed);
|
||||
participation.put (PEER_PROFILE_PARTICIPATION_DECLINED, m_NumTunnelsDeclined);
|
||||
participation.put (PEER_PROFILE_PARTICIPATION_NON_REPLIED, m_NumTunnelsNonReplied);
|
||||
boost::property_tree::ptree usage;
|
||||
usage.put (PEER_PROFILE_USAGE_TAKEN, m_NumTimesTaken);
|
||||
usage.put (PEER_PROFILE_USAGE_REJECTED, m_NumTimesRejected);
|
||||
// fill property tree
|
||||
boost::property_tree::ptree pt;
|
||||
pt.put (PEER_PROFILE_LAST_UPDATE_TIME, boost::posix_time::to_simple_string (m_LastUpdateTime));
|
||||
pt.put_child (PEER_PROFILE_SECTION_PARTICIPATION, participation);
|
||||
|
||||
pt.put_child (PEER_PROFILE_SECTION_USAGE, usage);
|
||||
|
||||
// save to file
|
||||
auto path = i2p::util::filesystem::GetDefaultDataDir() / PEER_PROFILES_DIRECTORY;
|
||||
if (!boost::filesystem::exists (path))
|
||||
@ -97,11 +101,29 @@ namespace data
|
||||
m_LastUpdateTime = boost::posix_time::time_from_string (t);
|
||||
if ((GetTime () - m_LastUpdateTime).hours () < PEER_PROFILE_EXPIRATION_TIMEOUT)
|
||||
{
|
||||
// read participations
|
||||
auto participations = pt.get_child (PEER_PROFILE_SECTION_PARTICIPATION);
|
||||
m_NumTunnelsAgreed = participations.get (PEER_PROFILE_PARTICIPATION_AGREED, 0);
|
||||
m_NumTunnelsDeclined = participations.get (PEER_PROFILE_PARTICIPATION_DECLINED, 0);
|
||||
m_NumTunnelsNonReplied = participations.get (PEER_PROFILE_PARTICIPATION_NON_REPLIED, 0);
|
||||
try
|
||||
{
|
||||
// read participations
|
||||
auto participations = pt.get_child (PEER_PROFILE_SECTION_PARTICIPATION);
|
||||
m_NumTunnelsAgreed = participations.get (PEER_PROFILE_PARTICIPATION_AGREED, 0);
|
||||
m_NumTunnelsDeclined = participations.get (PEER_PROFILE_PARTICIPATION_DECLINED, 0);
|
||||
m_NumTunnelsNonReplied = participations.get (PEER_PROFILE_PARTICIPATION_NON_REPLIED, 0);
|
||||
}
|
||||
catch (boost::property_tree::ptree_bad_path& ex)
|
||||
{
|
||||
LogPrint (eLogWarning, "Missing section ", PEER_PROFILE_SECTION_PARTICIPATION);
|
||||
}
|
||||
try
|
||||
{
|
||||
// read usage
|
||||
auto usage = pt.get_child (PEER_PROFILE_SECTION_USAGE);
|
||||
m_NumTimesTaken = usage.get (PEER_PROFILE_USAGE_TAKEN, 0);
|
||||
m_NumTimesRejected = usage.get (PEER_PROFILE_USAGE_REJECTED, 0);
|
||||
}
|
||||
catch (boost::property_tree::ptree_bad_path& ex)
|
||||
{
|
||||
LogPrint (eLogWarning, "Missing section ", PEER_PROFILE_SECTION_USAGE);
|
||||
}
|
||||
}
|
||||
else
|
||||
*this = RouterProfile (m_IdentHash);
|
||||
@ -115,11 +137,11 @@ namespace data
|
||||
|
||||
void RouterProfile::TunnelBuildResponse (uint8_t ret)
|
||||
{
|
||||
UpdateTime ();
|
||||
if (ret > 0)
|
||||
m_NumTunnelsDeclined++;
|
||||
else
|
||||
m_NumTunnelsAgreed++;
|
||||
UpdateTime ();
|
||||
}
|
||||
|
||||
void RouterProfile::TunnelNonReplied ()
|
||||
@ -128,27 +150,30 @@ namespace data
|
||||
UpdateTime ();
|
||||
}
|
||||
|
||||
bool RouterProfile::IsLowPartcipationRate (uint32_t elapsedTime) const
|
||||
bool RouterProfile::IsLowPartcipationRate () const
|
||||
{
|
||||
if (elapsedTime < 900) // if less than 15 minutes
|
||||
return m_NumTunnelsAgreed < m_NumTunnelsDeclined; // 50% rate
|
||||
else
|
||||
return 3*m_NumTunnelsAgreed < m_NumTunnelsDeclined; // 25% rate
|
||||
return 4*m_NumTunnelsAgreed < m_NumTunnelsDeclined; // < 20% rate
|
||||
}
|
||||
|
||||
bool RouterProfile::IsLowReplyRate (uint32_t elapsedTime) const
|
||||
bool RouterProfile::IsLowReplyRate () const
|
||||
{
|
||||
auto total = m_NumTunnelsAgreed + m_NumTunnelsDeclined;
|
||||
if (elapsedTime < 300) // if less than 5 minutes
|
||||
return m_NumTunnelsNonReplied > 5*(total + 1);
|
||||
else
|
||||
return !total && m_NumTunnelsNonReplied*15 > elapsedTime;
|
||||
return m_NumTunnelsNonReplied > 10*(total + 1);
|
||||
}
|
||||
|
||||
bool RouterProfile::IsBad () const
|
||||
bool RouterProfile::IsBad ()
|
||||
{
|
||||
auto elapsedTime = (GetTime () - m_LastUpdateTime).total_seconds ();
|
||||
return IsAlwaysDeclining () || IsLowPartcipationRate (elapsedTime) || IsLowReplyRate (elapsedTime);
|
||||
auto isBad = IsAlwaysDeclining () || IsLowPartcipationRate () /*|| IsLowReplyRate ()*/;
|
||||
if (isBad && m_NumTimesRejected > 10*(m_NumTimesTaken + 1))
|
||||
{
|
||||
// reset profile
|
||||
m_NumTunnelsAgreed = 0;
|
||||
m_NumTunnelsDeclined = 0;
|
||||
m_NumTunnelsNonReplied = 0;
|
||||
isBad = false;
|
||||
}
|
||||
if (isBad) m_NumTimesRejected++; else m_NumTimesTaken++;
|
||||
return isBad;
|
||||
}
|
||||
|
||||
std::shared_ptr<RouterProfile> GetRouterProfile (const IdentHash& identHash)
|
||||
|
12
Profiling.h
12
Profiling.h
@ -13,11 +13,14 @@ namespace data
|
||||
const char PEER_PROFILE_PREFIX[] = "profile-";
|
||||
// sections
|
||||
const char PEER_PROFILE_SECTION_PARTICIPATION[] = "participation";
|
||||
const char PEER_PROFILE_SECTION_USAGE[] = "usage";
|
||||
// params
|
||||
const char PEER_PROFILE_LAST_UPDATE_TIME[] = "lastupdatetime";
|
||||
const char PEER_PROFILE_PARTICIPATION_AGREED[] = "agreed";
|
||||
const char PEER_PROFILE_PARTICIPATION_DECLINED[] = "declined";
|
||||
const char PEER_PROFILE_PARTICIPATION_NON_REPLIED[] = "nonreplied";
|
||||
const char PEER_PROFILE_USAGE_TAKEN[] = "taken";
|
||||
const char PEER_PROFILE_USAGE_REJECTED[] = "rejected";
|
||||
|
||||
const int PEER_PROFILE_EXPIRATION_TIMEOUT = 72; // in hours (3 days)
|
||||
|
||||
@ -31,7 +34,7 @@ namespace data
|
||||
void Save ();
|
||||
void Load ();
|
||||
|
||||
bool IsBad () const;
|
||||
bool IsBad ();
|
||||
|
||||
void TunnelBuildResponse (uint8_t ret);
|
||||
void TunnelNonReplied ();
|
||||
@ -42,8 +45,8 @@ namespace data
|
||||
void UpdateTime ();
|
||||
|
||||
bool IsAlwaysDeclining () const { return !m_NumTunnelsAgreed && m_NumTunnelsDeclined >= 5; };
|
||||
bool IsLowPartcipationRate (uint32_t elapsedTime) const;
|
||||
bool IsLowReplyRate (uint32_t elapsedTime) const;
|
||||
bool IsLowPartcipationRate () const;
|
||||
bool IsLowReplyRate () const;
|
||||
|
||||
private:
|
||||
|
||||
@ -53,6 +56,9 @@ namespace data
|
||||
uint32_t m_NumTunnelsAgreed;
|
||||
uint32_t m_NumTunnelsDeclined;
|
||||
uint32_t m_NumTunnelsNonReplied;
|
||||
// usage
|
||||
uint32_t m_NumTimesTaken;
|
||||
uint32_t m_NumTimesRejected;
|
||||
};
|
||||
|
||||
std::shared_ptr<RouterProfile> GetRouterProfile (const IdentHash& identHash);
|
||||
|
30
Queue.h
30
Queue.h
@ -17,14 +17,14 @@ namespace util
|
||||
{
|
||||
public:
|
||||
|
||||
void Put (Element * e)
|
||||
void Put (Element e)
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_QueueMutex);
|
||||
m_Queue.push (e);
|
||||
m_NonEmpty.notify_one ();
|
||||
}
|
||||
|
||||
void Put (const std::vector<Element *>& vec)
|
||||
void Put (const std::vector<Element>& vec)
|
||||
{
|
||||
if (!vec.empty ())
|
||||
{
|
||||
@ -35,10 +35,10 @@ namespace util
|
||||
}
|
||||
}
|
||||
|
||||
Element * GetNext ()
|
||||
Element GetNext ()
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_QueueMutex);
|
||||
Element * el = GetNonThreadSafe ();
|
||||
auto el = GetNonThreadSafe ();
|
||||
if (!el)
|
||||
{
|
||||
m_NonEmpty.wait (l);
|
||||
@ -47,10 +47,10 @@ namespace util
|
||||
return el;
|
||||
}
|
||||
|
||||
Element * GetNextWithTimeout (int usec)
|
||||
Element GetNextWithTimeout (int usec)
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_QueueMutex);
|
||||
Element * el = GetNonThreadSafe ();
|
||||
auto el = GetNonThreadSafe ();
|
||||
if (!el)
|
||||
{
|
||||
m_NonEmpty.wait_for (l, std::chrono::milliseconds (usec));
|
||||
@ -85,13 +85,13 @@ namespace util
|
||||
|
||||
void WakeUp () { m_NonEmpty.notify_all (); };
|
||||
|
||||
Element * Get ()
|
||||
Element Get ()
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_QueueMutex);
|
||||
return GetNonThreadSafe ();
|
||||
}
|
||||
|
||||
Element * Peek ()
|
||||
Element Peek ()
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_QueueMutex);
|
||||
return GetNonThreadSafe (true);
|
||||
@ -99,11 +99,11 @@ namespace util
|
||||
|
||||
private:
|
||||
|
||||
Element * GetNonThreadSafe (bool peek = false)
|
||||
Element GetNonThreadSafe (bool peek = false)
|
||||
{
|
||||
if (!m_Queue.empty ())
|
||||
{
|
||||
Element * el = m_Queue.front ();
|
||||
auto el = m_Queue.front ();
|
||||
if (!peek)
|
||||
m_Queue.pop ();
|
||||
return el;
|
||||
@ -113,13 +113,13 @@ namespace util
|
||||
|
||||
private:
|
||||
|
||||
std::queue<Element *> m_Queue;
|
||||
std::queue<Element> m_Queue;
|
||||
std::mutex m_QueueMutex;
|
||||
std::condition_variable m_NonEmpty;
|
||||
};
|
||||
|
||||
template<class Msg>
|
||||
class MsgQueue: public Queue<Msg>
|
||||
class MsgQueue: public Queue<Msg *>
|
||||
{
|
||||
public:
|
||||
|
||||
@ -132,7 +132,7 @@ namespace util
|
||||
if (m_IsRunning)
|
||||
{
|
||||
m_IsRunning = false;
|
||||
Queue<Msg>::WakeUp ();
|
||||
Queue<Msg *>::WakeUp ();
|
||||
m_Thread.join();
|
||||
}
|
||||
}
|
||||
@ -145,7 +145,7 @@ namespace util
|
||||
{
|
||||
while (m_IsRunning)
|
||||
{
|
||||
while (Msg * msg = Queue<Msg>::Get ())
|
||||
while (auto msg = Queue<Msg *>::Get ())
|
||||
{
|
||||
msg->Process ();
|
||||
delete msg;
|
||||
@ -153,7 +153,7 @@ namespace util
|
||||
if (m_OnEmpty != nullptr)
|
||||
m_OnEmpty ();
|
||||
if (m_IsRunning)
|
||||
Queue<Msg>::Wait ();
|
||||
Queue<Msg *>::Wait ();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -299,6 +299,18 @@ namespace i2p
|
||||
i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from));
|
||||
}
|
||||
|
||||
void RouterContext::ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg)
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_GarlicMutex);
|
||||
i2p::garlic::GarlicDestination::ProcessGarlicMessage (msg);
|
||||
}
|
||||
|
||||
void RouterContext::ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg)
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_GarlicMutex);
|
||||
i2p::garlic::GarlicDestination::ProcessDeliveryStatusMessage (msg);
|
||||
}
|
||||
|
||||
uint32_t RouterContext::GetUptime () const
|
||||
{
|
||||
return i2p::util::GetSecondsSinceEpoch () - m_StartupTime;
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <inttypes.h>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <boost/asio.hpp>
|
||||
#include <cryptopp/dsa.h>
|
||||
#include <cryptopp/osrng.h>
|
||||
@ -75,6 +76,10 @@ namespace i2p
|
||||
std::shared_ptr<const i2p::data::LeaseSet> GetLeaseSet () { return nullptr; };
|
||||
std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () const;
|
||||
void HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from);
|
||||
|
||||
// override GarlicDestination
|
||||
void ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg);
|
||||
void ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
|
||||
|
||||
private:
|
||||
|
||||
@ -93,6 +98,7 @@ namespace i2p
|
||||
bool m_AcceptsTunnels, m_IsFloodfill;
|
||||
uint64_t m_StartupTime; // in seconds since epoch
|
||||
RouterStatus m_Status;
|
||||
std::mutex m_GarlicMutex;
|
||||
};
|
||||
|
||||
extern RouterContext context;
|
||||
|
@ -447,10 +447,13 @@ namespace data
|
||||
if (m_Buffer)
|
||||
{
|
||||
std::ofstream f (fullPath, std::ofstream::binary | std::ofstream::out);
|
||||
f.write ((char *)m_Buffer, m_BufferLen);
|
||||
}
|
||||
if (f.is_open ())
|
||||
f.write ((char *)m_Buffer, m_BufferLen);
|
||||
else
|
||||
LogPrint(eLogError, "Can't save RouterInfo to ", fullPath);
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "Can't save to file");
|
||||
LogPrint (eLogError, "Can't save RouterInfo m_Buffer==NULL");
|
||||
}
|
||||
|
||||
size_t RouterInfo::ReadString (char * str, std::istream& s)
|
||||
|
28
SAM.cpp
28
SAM.cpp
@ -85,6 +85,9 @@ namespace client
|
||||
else
|
||||
{
|
||||
m_Buffer[bytes_transferred] = 0;
|
||||
char * eol = (char *)memchr (m_Buffer, '\n', bytes_transferred);
|
||||
if (eol)
|
||||
*eol = 0;
|
||||
LogPrint ("SAM handshake ", m_Buffer);
|
||||
char * separator = strchr (m_Buffer, ' ');
|
||||
if (separator)
|
||||
@ -340,19 +343,24 @@ namespace client
|
||||
if (m_Session)
|
||||
{
|
||||
i2p::data::IdentityEx dest;
|
||||
dest.FromBase64 (destination);
|
||||
context.GetAddressBook ().InsertAddress (dest);
|
||||
auto leaseSet = m_Session->localDestination->FindLeaseSet (dest.GetIdentHash ());
|
||||
if (leaseSet)
|
||||
Connect (leaseSet);
|
||||
else
|
||||
size_t len = dest.FromBase64(destination);
|
||||
if (len > 0)
|
||||
{
|
||||
m_Session->localDestination->RequestDestination (dest.GetIdentHash (),
|
||||
std::bind (&SAMSocket::HandleConnectLeaseSetRequestComplete,
|
||||
shared_from_this (), std::placeholders::_1));
|
||||
context.GetAddressBook().InsertAddress(dest);
|
||||
auto leaseSet = m_Session->localDestination->FindLeaseSet(dest.GetIdentHash());
|
||||
if (leaseSet)
|
||||
Connect(leaseSet);
|
||||
else
|
||||
{
|
||||
m_Session->localDestination->RequestDestination(dest.GetIdentHash(),
|
||||
std::bind(&SAMSocket::HandleConnectLeaseSetRequestComplete,
|
||||
shared_from_this(), std::placeholders::_1));
|
||||
}
|
||||
}
|
||||
else
|
||||
SendMessageReply(SAM_SESSION_STATUS_INVALID_KEY, strlen(SAM_SESSION_STATUS_INVALID_KEY), true);
|
||||
}
|
||||
else
|
||||
else
|
||||
SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true);
|
||||
}
|
||||
|
||||
|
1
SAM.h
1
SAM.h
@ -28,6 +28,7 @@ namespace client
|
||||
const char SAM_SESSION_CREATE_REPLY_OK[] = "SESSION STATUS RESULT=OK DESTINATION=%s\n";
|
||||
const char SAM_SESSION_CREATE_DUPLICATED_ID[] = "SESSION STATUS RESULT=DUPLICATED_ID\n";
|
||||
const char SAM_SESSION_CREATE_DUPLICATED_DEST[] = "SESSION STATUS RESULT=DUPLICATED_DEST\n";
|
||||
const char SAM_SESSION_STATUS_INVALID_KEY[] = "SESSION STATUS RESULT=INVALID_KEY\n";
|
||||
const char SAM_STREAM_CONNECT[] = "STREAM CONNECT";
|
||||
const char SAM_STREAM_STATUS_OK[] = "STREAM STATUS RESULT=OK\n";
|
||||
const char SAM_STREAM_STATUS_INVALID_ID[] = "STREAM STATUS RESULT=INVALID_ID\n";
|
||||
|
13
SSUData.cpp
13
SSUData.cpp
@ -15,9 +15,8 @@ namespace transport
|
||||
if (msg->len + fragmentSize > msg->maxLen)
|
||||
{
|
||||
LogPrint (eLogInfo, "SSU I2NP message size ", msg->maxLen, " is not enough");
|
||||
I2NPMessage * newMsg = NewI2NPMessage ();
|
||||
auto newMsg = ToSharedI2NPMessage(NewI2NPMessage ());
|
||||
*newMsg = *msg;
|
||||
DeleteI2NPMessage (msg);
|
||||
msg = newMsg;
|
||||
}
|
||||
memcpy (msg->buf + msg->len, fragment, fragmentSize);
|
||||
@ -174,7 +173,7 @@ namespace transport
|
||||
if (it == m_IncompleteMessages.end ())
|
||||
{
|
||||
// create new message
|
||||
auto msg = NewI2NPShortMessage ();
|
||||
auto msg = ToSharedI2NPMessage (NewI2NPShortMessage ());
|
||||
msg->len -= I2NP_SHORT_HEADER_SIZE;
|
||||
it = m_IncompleteMessages.insert (std::make_pair (msgID,
|
||||
std::unique_ptr<IncompleteMessage>(new IncompleteMessage (msg)))).first;
|
||||
@ -244,10 +243,7 @@ namespace transport
|
||||
m_Handler.PutNextMessage (msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "SSU message ", msgID, " already received");
|
||||
i2p::DeleteI2NPMessage (msg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -259,7 +255,6 @@ namespace transport
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "SSU unexpected message ", (int)msg->GetTypeID ());
|
||||
DeleteI2NPMessage (msg);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -294,13 +289,12 @@ namespace transport
|
||||
ProcessFragments (buf);
|
||||
}
|
||||
|
||||
void SSUData::Send (i2p::I2NPMessage * msg)
|
||||
void SSUData::Send (std::shared_ptr<i2p::I2NPMessage> msg)
|
||||
{
|
||||
uint32_t msgID = msg->ToSSU ();
|
||||
if (m_SentMessages.count (msgID) > 0)
|
||||
{
|
||||
LogPrint (eLogWarning, "SSU message ", msgID, " already sent");
|
||||
DeleteI2NPMessage (msg);
|
||||
return;
|
||||
}
|
||||
if (m_SentMessages.empty ()) // schedule resend at first message only
|
||||
@ -368,7 +362,6 @@ namespace transport
|
||||
len = 0;
|
||||
fragmentNum++;
|
||||
}
|
||||
DeleteI2NPMessage (msg);
|
||||
}
|
||||
|
||||
void SSUData::SendMsgAck (uint32_t msgID)
|
||||
|
@ -59,13 +59,12 @@ namespace transport
|
||||
|
||||
struct IncompleteMessage
|
||||
{
|
||||
I2NPMessage * msg;
|
||||
std::shared_ptr<I2NPMessage> msg;
|
||||
int nextFragmentNum;
|
||||
uint32_t lastFragmentInsertTime; // in seconds
|
||||
std::set<std::unique_ptr<Fragment>, FragmentCmp> savedFragments;
|
||||
|
||||
IncompleteMessage (I2NPMessage * m): msg (m), nextFragmentNum (0), lastFragmentInsertTime (0) {};
|
||||
~IncompleteMessage () { if (msg) DeleteI2NPMessage (msg); };
|
||||
IncompleteMessage (std::shared_ptr<I2NPMessage> m): msg (m), nextFragmentNum (0), lastFragmentInsertTime (0) {};
|
||||
void AttachNextFragment (const uint8_t * fragment, size_t fragmentSize);
|
||||
};
|
||||
|
||||
@ -89,7 +88,7 @@ namespace transport
|
||||
|
||||
void ProcessMessage (uint8_t * buf, size_t len);
|
||||
void FlushReceivedMessage ();
|
||||
void Send (i2p::I2NPMessage * msg);
|
||||
void Send (std::shared_ptr<i2p::I2NPMessage> msg);
|
||||
|
||||
void UpdatePacketSize (const i2p::data::IdentHash& remoteIdent);
|
||||
|
||||
|
@ -783,7 +783,7 @@ namespace transport
|
||||
m_DHKeysPair = nullptr;
|
||||
}
|
||||
m_Data.Start ();
|
||||
m_Data.Send (CreateDatabaseStoreMsg ());
|
||||
m_Data.Send (ToSharedI2NPMessage(CreateDatabaseStoreMsg ()));
|
||||
transports.PeerConnected (shared_from_this ());
|
||||
if (m_PeerTest && (m_RemoteRouter && m_RemoteRouter->IsPeerTesting ()))
|
||||
SendPeerTest ();
|
||||
@ -832,39 +832,18 @@ namespace transport
|
||||
}
|
||||
}
|
||||
|
||||
void SSUSession::SendI2NPMessage (I2NPMessage * msg)
|
||||
{
|
||||
GetService ().post (std::bind (&SSUSession::PostI2NPMessage, shared_from_this (), msg));
|
||||
}
|
||||
|
||||
void SSUSession::PostI2NPMessage (I2NPMessage * msg)
|
||||
{
|
||||
if (msg)
|
||||
{
|
||||
if (m_State == eSessionStateEstablished)
|
||||
m_Data.Send (msg);
|
||||
else
|
||||
DeleteI2NPMessage (msg);
|
||||
}
|
||||
}
|
||||
|
||||
void SSUSession::SendI2NPMessages (const std::vector<I2NPMessage *>& msgs)
|
||||
void SSUSession::SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs)
|
||||
{
|
||||
GetService ().post (std::bind (&SSUSession::PostI2NPMessages, shared_from_this (), msgs));
|
||||
}
|
||||
|
||||
void SSUSession::PostI2NPMessages (std::vector<I2NPMessage *> msgs)
|
||||
void SSUSession::PostI2NPMessages (std::vector<std::shared_ptr<I2NPMessage> > msgs)
|
||||
{
|
||||
if (m_State == eSessionStateEstablished)
|
||||
{
|
||||
for (auto it: msgs)
|
||||
if (it) m_Data.Send (it);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto it: msgs)
|
||||
DeleteI2NPMessage (it);
|
||||
}
|
||||
}
|
||||
|
||||
void SSUSession::ProcessData (uint8_t * buf, size_t len)
|
||||
|
@ -76,8 +76,7 @@ namespace transport
|
||||
void Done ();
|
||||
boost::asio::ip::udp::endpoint& GetRemoteEndpoint () { return m_RemoteEndpoint; };
|
||||
bool IsV6 () const { return m_RemoteEndpoint.address ().is_v6 (); };
|
||||
void SendI2NPMessage (I2NPMessage * msg);
|
||||
void SendI2NPMessages (const std::vector<I2NPMessage *>& msgs);
|
||||
void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
|
||||
void SendPeerTest (); // Alice
|
||||
|
||||
SessionState GetState () const { return m_State; };
|
||||
@ -95,8 +94,7 @@ namespace transport
|
||||
boost::asio::io_service& GetService ();
|
||||
void CreateAESandMacKey (const uint8_t * pubKey);
|
||||
|
||||
void PostI2NPMessage (I2NPMessage * msg);
|
||||
void PostI2NPMessages (std::vector<I2NPMessage *> msgs);
|
||||
void PostI2NPMessages (std::vector<std::shared_ptr<I2NPMessage> > msgs);
|
||||
void ProcessMessage (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint); // call for established session
|
||||
void ProcessSessionRequest (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint);
|
||||
void SendSessionRequest ();
|
||||
|
@ -22,7 +22,7 @@ namespace stream
|
||||
{
|
||||
m_RecvStreamID = i2p::context.GetRandomNumberGenerator ().GenerateWord32 ();
|
||||
m_RemoteIdentity = remote->GetIdentity ();
|
||||
UpdateCurrentRemoteLease ();
|
||||
m_CurrentRemoteLease.endDate = 0;
|
||||
}
|
||||
|
||||
Stream::Stream (boost::asio::io_service& service, StreamingDestination& local):
|
||||
@ -761,9 +761,9 @@ namespace stream
|
||||
m_CurrentRemoteLease.endDate = 0;
|
||||
}
|
||||
|
||||
I2NPMessage * Stream::CreateDataMessage (const uint8_t * payload, size_t len)
|
||||
std::shared_ptr<I2NPMessage> Stream::CreateDataMessage (const uint8_t * payload, size_t len)
|
||||
{
|
||||
I2NPMessage * msg = NewI2NPShortMessage ();
|
||||
auto msg = ToSharedI2NPMessage (NewI2NPShortMessage ());
|
||||
CryptoPP::Gzip compressor;
|
||||
if (len <= i2p::stream::COMPRESSION_THRESHOLD_SIZE)
|
||||
compressor.SetDeflateLevel (CryptoPP::Gzip::MIN_DEFLATE_LEVEL);
|
||||
@ -780,7 +780,7 @@ namespace stream
|
||||
htobe16buf (buf + 6, m_Port); // destination port
|
||||
buf[9] = i2p::client::PROTOCOL_TYPE_STREAMING; // streaming protocol
|
||||
msg->len += size + 4;
|
||||
FillI2NPMessageHeader (msg, eI2NPData);
|
||||
msg->FillI2NPMessageHeader (eI2NPData);
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ namespace stream
|
||||
void HandleResendTimer (const boost::system::error_code& ecode);
|
||||
void HandleAckSendTimer (const boost::system::error_code& ecode);
|
||||
|
||||
I2NPMessage * CreateDataMessage (const uint8_t * payload, size_t len);
|
||||
std::shared_ptr<I2NPMessage> CreateDataMessage (const uint8_t * payload, size_t len);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -20,25 +20,24 @@ namespace tunnel
|
||||
m_Encryption.SetKeys (layerKey, ivKey);
|
||||
}
|
||||
|
||||
void TransitTunnel::EncryptTunnelMsg (I2NPMessage * tunnelMsg)
|
||||
void TransitTunnel::EncryptTunnelMsg (std::shared_ptr<const I2NPMessage> in, std::shared_ptr<I2NPMessage> out)
|
||||
{
|
||||
m_Encryption.Encrypt (tunnelMsg->GetPayload () + 4);
|
||||
m_Encryption.Encrypt (in->GetPayload () + 4, out->GetPayload () + 4);
|
||||
}
|
||||
|
||||
TransitTunnelParticipant::~TransitTunnelParticipant ()
|
||||
{
|
||||
for (auto it: m_TunnelDataMsgs)
|
||||
i2p::DeleteI2NPMessage (it);
|
||||
}
|
||||
|
||||
void TransitTunnelParticipant::HandleTunnelDataMsg (i2p::I2NPMessage * tunnelMsg)
|
||||
void TransitTunnelParticipant::HandleTunnelDataMsg (std::shared_ptr<const i2p::I2NPMessage> tunnelMsg)
|
||||
{
|
||||
EncryptTunnelMsg (tunnelMsg);
|
||||
auto newMsg = CreateEmptyTunnelDataMsg ();
|
||||
EncryptTunnelMsg (tunnelMsg, newMsg);
|
||||
|
||||
m_NumTransmittedBytes += tunnelMsg->GetLength ();
|
||||
htobe32buf (tunnelMsg->GetPayload (), GetNextTunnelID ());
|
||||
FillI2NPMessageHeader (tunnelMsg, eI2NPTunnelData);
|
||||
m_TunnelDataMsgs.push_back (tunnelMsg);
|
||||
htobe32buf (newMsg->GetPayload (), GetNextTunnelID ());
|
||||
newMsg->FillI2NPMessageHeader (eI2NPTunnelData);
|
||||
m_TunnelDataMsgs.push_back (newMsg);
|
||||
}
|
||||
|
||||
void TransitTunnelParticipant::FlushTunnelDataMsgs ()
|
||||
@ -53,19 +52,17 @@ namespace tunnel
|
||||
}
|
||||
}
|
||||
|
||||
void TransitTunnel::SendTunnelDataMsg (i2p::I2NPMessage * msg)
|
||||
void TransitTunnel::SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg)
|
||||
{
|
||||
LogPrint (eLogError, "We are not a gateway for transit tunnel ", m_TunnelID);
|
||||
i2p::DeleteI2NPMessage (msg);
|
||||
}
|
||||
|
||||
void TransitTunnel::HandleTunnelDataMsg (i2p::I2NPMessage * tunnelMsg)
|
||||
void TransitTunnel::HandleTunnelDataMsg (std::shared_ptr<const i2p::I2NPMessage> tunnelMsg)
|
||||
{
|
||||
LogPrint (eLogError, "Incoming tunnel message is not supported ", m_TunnelID);
|
||||
DeleteI2NPMessage (tunnelMsg);
|
||||
}
|
||||
|
||||
void TransitTunnelGateway::SendTunnelDataMsg (i2p::I2NPMessage * msg)
|
||||
void TransitTunnelGateway::SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg)
|
||||
{
|
||||
TunnelMessageBlock block;
|
||||
block.deliveryType = eDeliveryTypeLocal;
|
||||
@ -80,12 +77,13 @@ namespace tunnel
|
||||
m_Gateway.SendBuffer ();
|
||||
}
|
||||
|
||||
void TransitTunnelEndpoint::HandleTunnelDataMsg (i2p::I2NPMessage * tunnelMsg)
|
||||
void TransitTunnelEndpoint::HandleTunnelDataMsg (std::shared_ptr<const i2p::I2NPMessage> tunnelMsg)
|
||||
{
|
||||
EncryptTunnelMsg (tunnelMsg);
|
||||
auto newMsg = CreateEmptyTunnelDataMsg ();
|
||||
EncryptTunnelMsg (tunnelMsg, newMsg);
|
||||
|
||||
LogPrint (eLogDebug, "TransitTunnel endpoint for ", GetTunnelID ());
|
||||
m_Endpoint.HandleDecryptedTunnelDataMsg (tunnelMsg);
|
||||
m_Endpoint.HandleDecryptedTunnelDataMsg (newMsg);
|
||||
}
|
||||
|
||||
TransitTunnel * CreateTransitTunnel (uint32_t receiveTunnelID,
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <inttypes.h>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
#include "aes.h"
|
||||
#include "I2NPProtocol.h"
|
||||
#include "TunnelEndpoint.h"
|
||||
@ -27,9 +28,9 @@ namespace tunnel
|
||||
uint32_t GetTunnelID () const { return m_TunnelID; };
|
||||
|
||||
// implements TunnelBase
|
||||
void SendTunnelDataMsg (i2p::I2NPMessage * msg);
|
||||
void HandleTunnelDataMsg (i2p::I2NPMessage * tunnelMsg);
|
||||
void EncryptTunnelMsg (I2NPMessage * tunnelMsg);
|
||||
void SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg);
|
||||
void HandleTunnelDataMsg (std::shared_ptr<const i2p::I2NPMessage> tunnelMsg);
|
||||
void EncryptTunnelMsg (std::shared_ptr<const I2NPMessage> in, std::shared_ptr<I2NPMessage> out);
|
||||
uint32_t GetNextTunnelID () const { return m_NextTunnelID; };
|
||||
const i2p::data::IdentHash& GetNextIdentHash () const { return m_NextIdent; };
|
||||
|
||||
@ -53,13 +54,13 @@ namespace tunnel
|
||||
~TransitTunnelParticipant ();
|
||||
|
||||
size_t GetNumTransmittedBytes () const { return m_NumTransmittedBytes; };
|
||||
void HandleTunnelDataMsg (i2p::I2NPMessage * tunnelMsg);
|
||||
void HandleTunnelDataMsg (std::shared_ptr<const i2p::I2NPMessage> tunnelMsg);
|
||||
void FlushTunnelDataMsgs ();
|
||||
|
||||
private:
|
||||
|
||||
size_t m_NumTransmittedBytes;
|
||||
std::vector<i2p::I2NPMessage *> m_TunnelDataMsgs;
|
||||
std::vector<std::shared_ptr<i2p::I2NPMessage> > m_TunnelDataMsgs;
|
||||
};
|
||||
|
||||
class TransitTunnelGateway: public TransitTunnel
|
||||
@ -72,7 +73,7 @@ namespace tunnel
|
||||
TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID,
|
||||
layerKey, ivKey), m_Gateway(this) {};
|
||||
|
||||
void SendTunnelDataMsg (i2p::I2NPMessage * msg);
|
||||
void SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg);
|
||||
void FlushTunnelDataMsgs ();
|
||||
size_t GetNumTransmittedBytes () const { return m_Gateway.GetNumSentBytes (); };
|
||||
|
||||
@ -92,7 +93,7 @@ namespace tunnel
|
||||
TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey),
|
||||
m_Endpoint (false) {}; // transit endpoint is always outbound
|
||||
|
||||
void HandleTunnelDataMsg (i2p::I2NPMessage * tunnelMsg);
|
||||
void HandleTunnelDataMsg (std::shared_ptr<const i2p::I2NPMessage> tunnelMsg);
|
||||
size_t GetNumTransmittedBytes () const { return m_Endpoint.GetNumReceivedBytes (); }
|
||||
|
||||
private:
|
||||
|
@ -71,8 +71,7 @@ namespace transport
|
||||
size_t GetNumSentBytes () const { return m_NumSentBytes; };
|
||||
size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
|
||||
|
||||
virtual void SendI2NPMessage (I2NPMessage * msg) = 0;
|
||||
virtual void SendI2NPMessages (const std::vector<I2NPMessage *>& msgs) = 0;
|
||||
virtual void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -213,17 +213,17 @@ namespace transport
|
||||
return std::max (m_InBandwidth, m_OutBandwidth) > LOW_BANDWIDTH_LIMIT;
|
||||
}
|
||||
|
||||
void Transports::SendMessage (const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg)
|
||||
void Transports::SendMessage (const i2p::data::IdentHash& ident, std::shared_ptr<i2p::I2NPMessage> msg)
|
||||
{
|
||||
m_Service.post (std::bind (&Transports::PostMessages, this, ident, std::vector<i2p::I2NPMessage *> {msg}));
|
||||
SendMessages (ident, std::vector<std::shared_ptr<i2p::I2NPMessage> > {msg });
|
||||
}
|
||||
|
||||
void Transports::SendMessages (const i2p::data::IdentHash& ident, const std::vector<i2p::I2NPMessage *>& msgs)
|
||||
void Transports::SendMessages (const i2p::data::IdentHash& ident, const std::vector<std::shared_ptr<i2p::I2NPMessage> >& msgs)
|
||||
{
|
||||
m_Service.post (std::bind (&Transports::PostMessages, this, ident, msgs));
|
||||
}
|
||||
|
||||
void Transports::PostMessages (i2p::data::IdentHash ident, std::vector<i2p::I2NPMessage *> msgs)
|
||||
void Transports::PostMessages (i2p::data::IdentHash ident, std::vector<std::shared_ptr<i2p::I2NPMessage> > msgs)
|
||||
{
|
||||
if (ident == i2p::context.GetRouterInfo ().GetIdentHash ())
|
||||
{
|
||||
@ -239,7 +239,7 @@ namespace transport
|
||||
try
|
||||
{
|
||||
auto r = netdb.FindRouter (ident);
|
||||
it = m_Peers.insert (std::pair<i2p::data::IdentHash, Peer>(ident, { 0, r, nullptr,
|
||||
it = m_Peers.insert (std::pair<i2p::data::IdentHash, Peer>(ident, { 0, r, {},
|
||||
i2p::util::GetSecondsSinceEpoch () })).first;
|
||||
connected = ConnectToPeer (ident, it->second);
|
||||
}
|
||||
@ -247,15 +247,10 @@ namespace transport
|
||||
{
|
||||
LogPrint (eLogError, "Transports::PostMessages ", ex.what ());
|
||||
}
|
||||
if (!connected)
|
||||
{
|
||||
for (auto it1: msgs)
|
||||
DeleteI2NPMessage (it1);
|
||||
return;
|
||||
}
|
||||
if (!connected) return;
|
||||
}
|
||||
if (it->second.session)
|
||||
it->second.session->SendI2NPMessages (msgs);
|
||||
if (!it->second.sessions.empty ())
|
||||
it->second.sessions.front ()->SendI2NPMessages (msgs);
|
||||
else
|
||||
{
|
||||
for (auto it1: msgs)
|
||||
@ -309,7 +304,7 @@ namespace transport
|
||||
}
|
||||
}
|
||||
LogPrint (eLogError, "No NTCP and SSU addresses available");
|
||||
if (peer.session) peer.session->Done ();
|
||||
peer.Done ();
|
||||
m_Peers.erase (ident);
|
||||
return false;
|
||||
}
|
||||
@ -436,20 +431,12 @@ namespace transport
|
||||
auto it = m_Peers.find (ident);
|
||||
if (it != m_Peers.end ())
|
||||
{
|
||||
if (!it->second.session)
|
||||
{
|
||||
it->second.session = session;
|
||||
session->SendI2NPMessages (it->second.delayedMessages);
|
||||
it->second.delayedMessages.clear ();
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "Session for ", ident.ToBase64 ().substr (0, 4), " already exists");
|
||||
session->Done ();
|
||||
}
|
||||
it->second.sessions.push_back (session);
|
||||
session->SendI2NPMessages (it->second.delayedMessages);
|
||||
it->second.delayedMessages.clear ();
|
||||
}
|
||||
else // incoming connection
|
||||
m_Peers.insert (std::make_pair (ident, Peer{ 0, nullptr, session, i2p::util::GetSecondsSinceEpoch () }));
|
||||
m_Peers.insert (std::make_pair (ident, Peer{ 0, nullptr, { session }, i2p::util::GetSecondsSinceEpoch () }));
|
||||
});
|
||||
}
|
||||
|
||||
@ -459,12 +446,16 @@ namespace transport
|
||||
{
|
||||
auto ident = session->GetRemoteIdentity ().GetIdentHash ();
|
||||
auto it = m_Peers.find (ident);
|
||||
if (it != m_Peers.end () && (!it->second.session || it->second.session == session))
|
||||
if (it != m_Peers.end ())
|
||||
{
|
||||
if (it->second.delayedMessages.size () > 0)
|
||||
ConnectToPeer (ident, it->second);
|
||||
else
|
||||
m_Peers.erase (it);
|
||||
it->second.sessions.remove (session);
|
||||
if (it->second.sessions.empty ()) // TODO: why?
|
||||
{
|
||||
if (it->second.delayedMessages.size () > 0)
|
||||
ConnectToPeer (ident, it->second);
|
||||
else
|
||||
m_Peers.erase (it);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -482,7 +473,7 @@ namespace transport
|
||||
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
||||
for (auto it = m_Peers.begin (); it != m_Peers.end (); )
|
||||
{
|
||||
if (!it->second.session && ts > it->second.creationTime + SESSION_CREATION_TIMEOUT)
|
||||
if (it->second.sessions.empty () && ts > it->second.creationTime + SESSION_CREATION_TIMEOUT)
|
||||
{
|
||||
LogPrint (eLogError, "Session to peer ", it->first.ToBase64 (), " has not been created in ", SESSION_CREATION_TIMEOUT, " seconds");
|
||||
it = m_Peers.erase (it);
|
||||
|
16
Transports.h
16
Transports.h
@ -60,14 +60,14 @@ namespace transport
|
||||
{
|
||||
int numAttempts;
|
||||
std::shared_ptr<const i2p::data::RouterInfo> router;
|
||||
std::shared_ptr<TransportSession> session;
|
||||
std::list<std::shared_ptr<TransportSession> > sessions;
|
||||
uint64_t creationTime;
|
||||
std::vector<i2p::I2NPMessage *> delayedMessages;
|
||||
std::vector<std::shared_ptr<i2p::I2NPMessage> > delayedMessages;
|
||||
|
||||
~Peer ()
|
||||
void Done ()
|
||||
{
|
||||
for (auto it :delayedMessages)
|
||||
i2p::DeleteI2NPMessage (it);
|
||||
for (auto it: sessions)
|
||||
it->Done ();
|
||||
}
|
||||
};
|
||||
|
||||
@ -87,8 +87,8 @@ namespace transport
|
||||
i2p::transport::DHKeysPair * GetNextDHKeysPair ();
|
||||
void ReuseDHKeysPair (DHKeysPair * pair);
|
||||
|
||||
void SendMessage (const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg);
|
||||
void SendMessages (const i2p::data::IdentHash& ident, const std::vector<i2p::I2NPMessage *>& msgs);
|
||||
void SendMessage (const i2p::data::IdentHash& ident, std::shared_ptr<i2p::I2NPMessage> msg);
|
||||
void SendMessages (const i2p::data::IdentHash& ident, const std::vector<std::shared_ptr<i2p::I2NPMessage> >& msgs);
|
||||
void CloseSession (std::shared_ptr<const i2p::data::RouterInfo> router);
|
||||
|
||||
void PeerConnected (std::shared_ptr<TransportSession> session);
|
||||
@ -110,7 +110,7 @@ namespace transport
|
||||
void Run ();
|
||||
void RequestComplete (std::shared_ptr<const i2p::data::RouterInfo> r, const i2p::data::IdentHash& ident);
|
||||
void HandleRequestComplete (std::shared_ptr<const i2p::data::RouterInfo> r, const i2p::data::IdentHash& ident);
|
||||
void PostMessages (i2p::data::IdentHash ident, std::vector<i2p::I2NPMessage *> msgs);
|
||||
void PostMessages (i2p::data::IdentHash ident, std::vector<std::shared_ptr<i2p::I2NPMessage> > msgs);
|
||||
void PostCloseSession (std::shared_ptr<const i2p::data::RouterInfo> router);
|
||||
bool ConnectToPeer (const i2p::data::IdentHash& ident, Peer& peer);
|
||||
void HandlePeerCleanupTimer (const boost::system::error_code& ecode);
|
||||
|
63
Tunnel.cpp
63
Tunnel.cpp
@ -31,7 +31,7 @@ namespace tunnel
|
||||
CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator ();
|
||||
auto numHops = m_Config->GetNumHops ();
|
||||
int numRecords = numHops <= STANDARD_NUM_RECORDS ? STANDARD_NUM_RECORDS : numHops;
|
||||
I2NPMessage * msg = NewI2NPShortMessage ();
|
||||
auto msg = NewI2NPShortMessage ();
|
||||
*msg->GetPayload () = numRecords;
|
||||
msg->len += numRecords*TUNNEL_BUILD_RECORD_SIZE + 1;
|
||||
|
||||
@ -77,13 +77,13 @@ namespace tunnel
|
||||
}
|
||||
hop = hop->prev;
|
||||
}
|
||||
FillI2NPMessageHeader (msg, eI2NPVariableTunnelBuild);
|
||||
msg->FillI2NPMessageHeader (eI2NPVariableTunnelBuild);
|
||||
|
||||
// send message
|
||||
if (outboundTunnel)
|
||||
outboundTunnel->SendTunnelDataMsg (GetNextIdentHash (), 0, msg);
|
||||
outboundTunnel->SendTunnelDataMsg (GetNextIdentHash (), 0, ToSharedI2NPMessage (msg));
|
||||
else
|
||||
i2p::transport::transports.SendMessage (GetNextIdentHash (), msg);
|
||||
i2p::transport::transports.SendMessage (GetNextIdentHash (), ToSharedI2NPMessage (msg));
|
||||
}
|
||||
|
||||
bool Tunnel::HandleTunnelBuildResponse (uint8_t * msg, size_t len)
|
||||
@ -140,32 +140,34 @@ namespace tunnel
|
||||
return established;
|
||||
}
|
||||
|
||||
void Tunnel::EncryptTunnelMsg (I2NPMessage * tunnelMsg)
|
||||
void Tunnel::EncryptTunnelMsg (std::shared_ptr<const I2NPMessage> in, std::shared_ptr<I2NPMessage> out)
|
||||
{
|
||||
uint8_t * payload = tunnelMsg->GetPayload () + 4;
|
||||
const uint8_t * inPayload = in->GetPayload () + 4;
|
||||
uint8_t * outPayload = out->GetPayload () + 4;
|
||||
TunnelHopConfig * hop = m_Config->GetLastHop ();
|
||||
while (hop)
|
||||
{
|
||||
hop->decryption.Decrypt (payload);
|
||||
hop->decryption.Decrypt (inPayload, outPayload);
|
||||
hop = hop->prev;
|
||||
inPayload = outPayload;
|
||||
}
|
||||
}
|
||||
|
||||
void Tunnel::SendTunnelDataMsg (i2p::I2NPMessage * msg)
|
||||
void Tunnel::SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg)
|
||||
{
|
||||
LogPrint (eLogInfo, "Can't send I2NP messages without delivery instructions");
|
||||
DeleteI2NPMessage (msg);
|
||||
}
|
||||
|
||||
void InboundTunnel::HandleTunnelDataMsg (I2NPMessage * msg)
|
||||
void InboundTunnel::HandleTunnelDataMsg (std::shared_ptr<const I2NPMessage> msg)
|
||||
{
|
||||
if (IsFailed ()) SetState (eTunnelStateEstablished); // incoming messages means a tunnel is alive
|
||||
msg->from = shared_from_this ();
|
||||
EncryptTunnelMsg (msg);
|
||||
m_Endpoint.HandleDecryptedTunnelDataMsg (msg);
|
||||
if (IsFailed ()) SetState (eTunnelStateEstablished); // incoming messages means a tunnel is alive
|
||||
auto newMsg = CreateEmptyTunnelDataMsg ();
|
||||
EncryptTunnelMsg (msg, newMsg);
|
||||
newMsg->from = shared_from_this ();
|
||||
m_Endpoint.HandleDecryptedTunnelDataMsg (newMsg);
|
||||
}
|
||||
|
||||
void OutboundTunnel::SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, i2p::I2NPMessage * msg)
|
||||
void OutboundTunnel::SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr<i2p::I2NPMessage> msg)
|
||||
{
|
||||
TunnelMessageBlock block;
|
||||
if (gwHash)
|
||||
@ -195,10 +197,9 @@ namespace tunnel
|
||||
m_Gateway.SendBuffer ();
|
||||
}
|
||||
|
||||
void OutboundTunnel::HandleTunnelDataMsg (i2p::I2NPMessage * tunnelMsg)
|
||||
void OutboundTunnel::HandleTunnelDataMsg (std::shared_ptr<const i2p::I2NPMessage> tunnelMsg)
|
||||
{
|
||||
LogPrint (eLogError, "Incoming message for outbound tunnel ", GetTunnelID ());
|
||||
DeleteI2NPMessage (tunnelMsg);
|
||||
}
|
||||
|
||||
Tunnels tunnels;
|
||||
@ -352,7 +353,7 @@ namespace tunnel
|
||||
{
|
||||
try
|
||||
{
|
||||
I2NPMessage * msg = m_Queue.GetNextWithTimeout (1000); // 1 sec
|
||||
auto msg = m_Queue.GetNextWithTimeout (1000); // 1 sec
|
||||
if (msg)
|
||||
{
|
||||
uint32_t prevTunnelID = 0, tunnelID = 0;
|
||||
@ -383,27 +384,18 @@ namespace tunnel
|
||||
else // tunnel gateway assumed
|
||||
HandleTunnelGatewayMsg (tunnel, msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
else
|
||||
LogPrint (eLogWarning, "Tunnel ", tunnelID, " not found");
|
||||
DeleteI2NPMessage (msg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case eI2NPVariableTunnelBuild:
|
||||
case eI2NPVariableTunnelBuildReply:
|
||||
case eI2NPTunnelBuild:
|
||||
case eI2NPTunnelBuildReply:
|
||||
{
|
||||
HandleI2NPMessage (msg->GetBuffer (), msg->GetLength ());
|
||||
DeleteI2NPMessage (msg);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
LogPrint (eLogError, "Unexpected messsage type ", (int)typeID);
|
||||
DeleteI2NPMessage (msg);
|
||||
}
|
||||
}
|
||||
|
||||
msg = m_Queue.Get ();
|
||||
@ -432,12 +424,11 @@ namespace tunnel
|
||||
}
|
||||
}
|
||||
|
||||
void Tunnels::HandleTunnelGatewayMsg (TunnelBase * tunnel, I2NPMessage * msg)
|
||||
void Tunnels::HandleTunnelGatewayMsg (TunnelBase * tunnel, std::shared_ptr<I2NPMessage> msg)
|
||||
{
|
||||
if (!tunnel)
|
||||
{
|
||||
LogPrint (eLogError, "Missing tunnel for TunnelGateway");
|
||||
i2p::DeleteI2NPMessage (msg);
|
||||
return;
|
||||
}
|
||||
const uint8_t * payload = msg->GetPayload ();
|
||||
@ -449,13 +440,9 @@ namespace tunnel
|
||||
LogPrint (eLogDebug, "TunnelGateway of ", (int)len, " bytes for tunnel ", tunnel->GetTunnelID (), ". Msg type ", (int)typeID);
|
||||
|
||||
if (typeID == eI2NPDatabaseStore || typeID == eI2NPDatabaseSearchReply)
|
||||
{
|
||||
// transit DatabaseStore my contain new/updated RI
|
||||
// or DatabaseSearchReply with new routers
|
||||
auto ds = NewI2NPMessage ();
|
||||
*ds = *msg;
|
||||
i2p::data::netdb.PostI2NPMsg (ds);
|
||||
}
|
||||
i2p::data::netdb.PostI2NPMsg (msg);
|
||||
tunnel->SendTunnelDataMsg (msg);
|
||||
}
|
||||
|
||||
@ -661,12 +648,12 @@ namespace tunnel
|
||||
}
|
||||
}
|
||||
|
||||
void Tunnels::PostTunnelData (I2NPMessage * msg)
|
||||
void Tunnels::PostTunnelData (std::shared_ptr<I2NPMessage> msg)
|
||||
{
|
||||
if (msg) m_Queue.Put (msg);
|
||||
}
|
||||
|
||||
void Tunnels::PostTunnelData (const std::vector<I2NPMessage *>& msgs)
|
||||
void Tunnels::PostTunnelData (const std::vector<std::shared_ptr<I2NPMessage> >& msgs)
|
||||
{
|
||||
m_Queue.Put (msgs);
|
||||
}
|
||||
|
18
Tunnel.h
18
Tunnel.h
@ -64,8 +64,8 @@ namespace tunnel
|
||||
bool HandleTunnelBuildResponse (uint8_t * msg, size_t len);
|
||||
|
||||
// implements TunnelBase
|
||||
void SendTunnelDataMsg (i2p::I2NPMessage * msg);
|
||||
void EncryptTunnelMsg (I2NPMessage * tunnelMsg);
|
||||
void SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg);
|
||||
void EncryptTunnelMsg (std::shared_ptr<const I2NPMessage> in, std::shared_ptr<I2NPMessage> out);
|
||||
uint32_t GetNextTunnelID () const { return m_Config->GetFirstHop ()->tunnelID; };
|
||||
const i2p::data::IdentHash& GetNextIdentHash () const { return m_Config->GetFirstHop ()->router->GetIdentHash (); };
|
||||
|
||||
@ -83,14 +83,14 @@ namespace tunnel
|
||||
|
||||
OutboundTunnel (std::shared_ptr<const TunnelConfig> config): Tunnel (config), m_Gateway (this) {};
|
||||
|
||||
void SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, i2p::I2NPMessage * msg);
|
||||
void SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr<i2p::I2NPMessage> msg);
|
||||
void SendTunnelDataMsg (const std::vector<TunnelMessageBlock>& msgs); // multiple messages
|
||||
std::shared_ptr<const i2p::data::RouterInfo> GetEndpointRouter () const
|
||||
{ return GetTunnelConfig ()->GetLastHop ()->router; };
|
||||
size_t GetNumSentBytes () const { return m_Gateway.GetNumSentBytes (); };
|
||||
|
||||
// implements TunnelBase
|
||||
void HandleTunnelDataMsg (i2p::I2NPMessage * tunnelMsg);
|
||||
void HandleTunnelDataMsg (std::shared_ptr<const i2p::I2NPMessage> tunnelMsg);
|
||||
uint32_t GetTunnelID () const { return GetNextTunnelID (); };
|
||||
|
||||
private:
|
||||
@ -104,7 +104,7 @@ namespace tunnel
|
||||
public:
|
||||
|
||||
InboundTunnel (std::shared_ptr<const TunnelConfig> config): Tunnel (config), m_Endpoint (true) {};
|
||||
void HandleTunnelDataMsg (I2NPMessage * msg);
|
||||
void HandleTunnelDataMsg (std::shared_ptr<const I2NPMessage> msg);
|
||||
size_t GetNumReceivedBytes () const { return m_Endpoint.GetNumReceivedBytes (); };
|
||||
|
||||
// implements TunnelBase
|
||||
@ -135,8 +135,8 @@ namespace tunnel
|
||||
void AddTransitTunnel (TransitTunnel * tunnel);
|
||||
void AddOutboundTunnel (std::shared_ptr<OutboundTunnel> newTunnel);
|
||||
void AddInboundTunnel (std::shared_ptr<InboundTunnel> newTunnel);
|
||||
void PostTunnelData (I2NPMessage * msg);
|
||||
void PostTunnelData (const std::vector<I2NPMessage *>& msgs);
|
||||
void PostTunnelData (std::shared_ptr<I2NPMessage> msg);
|
||||
void PostTunnelData (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
|
||||
template<class TTunnel>
|
||||
std::shared_ptr<TTunnel> CreateTunnel (std::shared_ptr<TunnelConfig> config, std::shared_ptr<OutboundTunnel> outboundTunnel = nullptr);
|
||||
void AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr<InboundTunnel> tunnel);
|
||||
@ -150,7 +150,7 @@ namespace tunnel
|
||||
template<class TTunnel>
|
||||
std::shared_ptr<TTunnel> GetPendingTunnel (uint32_t replyMsgID, const std::map<uint32_t, std::shared_ptr<TTunnel> >& pendingTunnels);
|
||||
|
||||
void HandleTunnelGatewayMsg (TunnelBase * tunnel, I2NPMessage * msg);
|
||||
void HandleTunnelGatewayMsg (TunnelBase * tunnel, std::shared_ptr<I2NPMessage> msg);
|
||||
|
||||
void Run ();
|
||||
void ManageTunnels ();
|
||||
@ -177,7 +177,7 @@ namespace tunnel
|
||||
std::mutex m_PoolsMutex;
|
||||
std::list<std::shared_ptr<TunnelPool>> m_Pools;
|
||||
std::shared_ptr<TunnelPool> m_ExploratoryPool;
|
||||
i2p::util::Queue<I2NPMessage> m_Queue;
|
||||
i2p::util::Queue<std::shared_ptr<I2NPMessage> > m_Queue;
|
||||
|
||||
// some stats
|
||||
int m_NumSuccesiveTunnelCreations, m_NumFailedTunnelCreations;
|
||||
|
@ -26,7 +26,7 @@ namespace tunnel
|
||||
TunnelDeliveryType deliveryType;
|
||||
i2p::data::IdentHash hash;
|
||||
uint32_t tunnelID;
|
||||
I2NPMessage * data;
|
||||
std::shared_ptr<I2NPMessage> data;
|
||||
};
|
||||
|
||||
class TunnelBase
|
||||
@ -37,10 +37,10 @@ namespace tunnel
|
||||
TunnelBase (): m_CreationTime (i2p::util::GetSecondsSinceEpoch ()) {};
|
||||
virtual ~TunnelBase () {};
|
||||
|
||||
virtual void HandleTunnelDataMsg (i2p::I2NPMessage * tunnelMsg) = 0;
|
||||
virtual void SendTunnelDataMsg (i2p::I2NPMessage * msg) = 0;
|
||||
virtual void HandleTunnelDataMsg (std::shared_ptr<const i2p::I2NPMessage> tunnelMsg) = 0;
|
||||
virtual void SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg) = 0;
|
||||
virtual void FlushTunnelDataMsgs () {};
|
||||
virtual void EncryptTunnelMsg (I2NPMessage * tunnelMsg) = 0;
|
||||
virtual void EncryptTunnelMsg (std::shared_ptr<const I2NPMessage> in, std::shared_ptr<I2NPMessage> out) = 0;
|
||||
virtual uint32_t GetNextTunnelID () const = 0;
|
||||
virtual const i2p::data::IdentHash& GetNextIdentHash () const = 0;
|
||||
virtual uint32_t GetTunnelID () const = 0; // as known at our side
|
||||
|
@ -13,13 +13,9 @@ namespace tunnel
|
||||
{
|
||||
TunnelEndpoint::~TunnelEndpoint ()
|
||||
{
|
||||
for (auto it: m_IncompleteMessages)
|
||||
i2p::DeleteI2NPMessage (it.second.data);
|
||||
for (auto it: m_OutOfSequenceFragments)
|
||||
i2p::DeleteI2NPMessage (it.second.data);
|
||||
}
|
||||
|
||||
void TunnelEndpoint::HandleDecryptedTunnelDataMsg (I2NPMessage * msg)
|
||||
void TunnelEndpoint::HandleDecryptedTunnelDataMsg (std::shared_ptr<I2NPMessage> msg)
|
||||
{
|
||||
m_NumReceivedBytes += TUNNEL_DATA_MSG_SIZE;
|
||||
|
||||
@ -35,7 +31,6 @@ namespace tunnel
|
||||
if (memcmp (hash, decrypted, 4))
|
||||
{
|
||||
LogPrint (eLogError, "TunnelMessage: checksum verification failed");
|
||||
i2p::DeleteI2NPMessage (msg);
|
||||
return;
|
||||
}
|
||||
// process fragments
|
||||
@ -97,7 +92,7 @@ namespace tunnel
|
||||
if (fragment + size < decrypted + TUNNEL_DATA_ENCRYPTED_SIZE)
|
||||
{
|
||||
// this is not last message. we have to copy it
|
||||
m.data = NewI2NPShortMessage ();
|
||||
m.data = ToSharedI2NPMessage (NewI2NPShortMessage ());
|
||||
m.data->offset += TUNNEL_GATEWAY_HEADER_SIZE; // reserve room for TunnelGateway header
|
||||
m.data->len += TUNNEL_GATEWAY_HEADER_SIZE;
|
||||
*(m.data) = *msg;
|
||||
@ -118,10 +113,7 @@ namespace tunnel
|
||||
if (ret.second)
|
||||
HandleOutOfSequenceFragment (msgID, ret.first->second);
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "Incomplete message ", msgID, "already exists");
|
||||
DeleteI2NPMessage (m.data);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -130,20 +122,14 @@ namespace tunnel
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "Message is fragmented, but msgID is not presented");
|
||||
DeleteI2NPMessage (m.data);
|
||||
}
|
||||
}
|
||||
|
||||
fragment += size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "TunnelMessage: zero not found");
|
||||
i2p::DeleteI2NPMessage (msg);
|
||||
}
|
||||
}
|
||||
|
||||
void TunnelEndpoint::HandleFollowOnFragment (uint32_t msgID, bool isLastFragment, const TunnelMessageBlockEx& m)
|
||||
@ -161,9 +147,8 @@ namespace tunnel
|
||||
if (msg.data->len + size > msg.data->maxLen)
|
||||
{
|
||||
LogPrint (eLogInfo, "Tunnel endpoint I2NP message size ", msg.data->maxLen, " is not enough");
|
||||
I2NPMessage * newMsg = NewI2NPMessage ();
|
||||
auto newMsg = ToSharedI2NPMessage (NewI2NPMessage ());
|
||||
*newMsg = *(msg.data);
|
||||
DeleteI2NPMessage (msg.data);
|
||||
msg.data = newMsg;
|
||||
}
|
||||
memcpy (msg.data->buf + msg.data->len, fragment, size); // concatenate fragment
|
||||
@ -183,10 +168,8 @@ namespace tunnel
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "Fragment ", m.nextFragmentNum, " of message ", msgID, "exceeds max I2NP message size. Message dropped");
|
||||
i2p::DeleteI2NPMessage (msg.data);
|
||||
m_IncompleteMessages.erase (it);
|
||||
}
|
||||
i2p::DeleteI2NPMessage (m.data);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -201,13 +184,11 @@ namespace tunnel
|
||||
}
|
||||
}
|
||||
|
||||
void TunnelEndpoint::AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, bool isLastFragment, I2NPMessage * data)
|
||||
void TunnelEndpoint::AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, bool isLastFragment, std::shared_ptr<I2NPMessage> data)
|
||||
{
|
||||
auto it = m_OutOfSequenceFragments.find (msgID);
|
||||
if (it == m_OutOfSequenceFragments.end ())
|
||||
m_OutOfSequenceFragments.insert (std::pair<uint32_t, Fragment> (msgID, {fragmentNum, isLastFragment, data}));
|
||||
else
|
||||
i2p::DeleteI2NPMessage (data);
|
||||
}
|
||||
|
||||
void TunnelEndpoint::HandleOutOfSequenceFragment (uint32_t msgID, TunnelMessageBlockEx& msg)
|
||||
@ -222,9 +203,8 @@ namespace tunnel
|
||||
if (msg.data->len + size > msg.data->maxLen)
|
||||
{
|
||||
LogPrint (eLogInfo, "Tunnel endpoint I2NP message size ", msg.data->maxLen, " is not enough");
|
||||
I2NPMessage * newMsg = NewI2NPMessage ();
|
||||
auto newMsg = ToSharedI2NPMessage (NewI2NPMessage ());
|
||||
*newMsg = *(msg.data);
|
||||
DeleteI2NPMessage (msg.data);
|
||||
msg.data = newMsg;
|
||||
}
|
||||
memcpy (msg.data->buf + msg.data->len, it->second.data->GetBuffer (), size); // concatenate out-of-sync fragment
|
||||
@ -237,7 +217,6 @@ namespace tunnel
|
||||
}
|
||||
else
|
||||
msg.nextFragmentNum++;
|
||||
i2p::DeleteI2NPMessage (it->second.data);
|
||||
m_OutOfSequenceFragments.erase (it);
|
||||
}
|
||||
}
|
||||
@ -262,28 +241,18 @@ namespace tunnel
|
||||
// to somebody else
|
||||
if (!m_IsInbound) // outbound transit tunnel
|
||||
{
|
||||
auto typeID = msg.data->GetTypeID ();
|
||||
/* auto typeID = msg.data->GetTypeID ();
|
||||
if (typeID == eI2NPDatabaseStore || typeID == eI2NPDatabaseSearchReply )
|
||||
{
|
||||
// catch RI or reply with new list of routers
|
||||
auto ds = NewI2NPShortMessage ();
|
||||
*ds = *(msg.data);
|
||||
i2p::data::netdb.PostI2NPMsg (ds);
|
||||
}
|
||||
i2p::data::netdb.PostI2NPMsg (msg.data);*/
|
||||
i2p::transport::transports.SendMessage (msg.hash, msg.data);
|
||||
}
|
||||
else // we shouldn't send this message. possible leakage
|
||||
{
|
||||
LogPrint (eLogError, "Message to another router arrived from an inbound tunnel. Dropped");
|
||||
i2p::DeleteI2NPMessage (msg.data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
LogPrint (eLogError, "TunnelMessage: Unknown delivery type ", (int)msg.deliveryType);
|
||||
i2p::DeleteI2NPMessage (msg.data);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ namespace tunnel
|
||||
{
|
||||
uint8_t fragmentNum;
|
||||
bool isLastFragment;
|
||||
I2NPMessage * data;
|
||||
std::shared_ptr<I2NPMessage> data;
|
||||
};
|
||||
|
||||
public:
|
||||
@ -31,14 +31,14 @@ namespace tunnel
|
||||
~TunnelEndpoint ();
|
||||
size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
|
||||
|
||||
void HandleDecryptedTunnelDataMsg (I2NPMessage * msg);
|
||||
void HandleDecryptedTunnelDataMsg (std::shared_ptr<I2NPMessage> msg);
|
||||
|
||||
private:
|
||||
|
||||
void HandleFollowOnFragment (uint32_t msgID, bool isLastFragment, const TunnelMessageBlockEx& m);
|
||||
void HandleNextMessage (const TunnelMessageBlock& msg);
|
||||
|
||||
void AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, bool isLastFragment, I2NPMessage * data);
|
||||
void AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, bool isLastFragment, std::shared_ptr<I2NPMessage> data);
|
||||
void HandleOutOfSequenceFragment (uint32_t msgID, TunnelMessageBlockEx& msg);
|
||||
|
||||
private:
|
||||
|
@ -10,10 +10,16 @@ namespace i2p
|
||||
{
|
||||
namespace tunnel
|
||||
{
|
||||
TunnelGatewayBuffer::TunnelGatewayBuffer (uint32_t tunnelID): m_TunnelID (tunnelID),
|
||||
m_CurrentTunnelDataMsg (nullptr), m_RemainingSize (0)
|
||||
{
|
||||
context.GetRandomNumberGenerator ().GenerateBlock (m_NonZeroRandomBuffer, TUNNEL_DATA_MAX_PAYLOAD_SIZE);
|
||||
for (size_t i = 0; i < TUNNEL_DATA_MAX_PAYLOAD_SIZE; i++)
|
||||
if (!m_NonZeroRandomBuffer[i]) m_NonZeroRandomBuffer[i] = 1;
|
||||
}
|
||||
|
||||
TunnelGatewayBuffer::~TunnelGatewayBuffer ()
|
||||
{
|
||||
for (auto it: m_TunnelDataMsgs)
|
||||
DeleteI2NPMessage (it);
|
||||
}
|
||||
|
||||
void TunnelGatewayBuffer::PutI2NPMsg (const TunnelMessageBlock& block)
|
||||
@ -42,7 +48,7 @@ namespace tunnel
|
||||
di[0] = block.deliveryType << 5; // set delivery type
|
||||
|
||||
// create fragments
|
||||
I2NPMessage * msg = block.data;
|
||||
std::shared_ptr<I2NPMessage> msg = block.data;
|
||||
auto fullMsgLen = diLen + msg->GetLength () + 2; // delivery instructions + payload + 2 bytes length
|
||||
if (fullMsgLen <= m_RemainingSize)
|
||||
{
|
||||
@ -55,7 +61,6 @@ namespace tunnel
|
||||
m_RemainingSize -= diLen + msg->GetLength ();
|
||||
if (!m_RemainingSize)
|
||||
CompleteCurrentTunnelDataMessage ();
|
||||
DeleteI2NPMessage (msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -119,7 +124,6 @@ namespace tunnel
|
||||
size += s;
|
||||
fragmentNumber++;
|
||||
}
|
||||
DeleteI2NPMessage (msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -138,7 +142,7 @@ namespace tunnel
|
||||
|
||||
void TunnelGatewayBuffer::CreateCurrentTunnelDataMessage ()
|
||||
{
|
||||
m_CurrentTunnelDataMsg = NewI2NPShortMessage ();
|
||||
m_CurrentTunnelDataMsg = ToSharedI2NPMessage (NewI2NPShortMessage ());
|
||||
m_CurrentTunnelDataMsg->Align (12);
|
||||
// we reserve space for padding
|
||||
m_CurrentTunnelDataMsg->offset += TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE;
|
||||
@ -164,13 +168,17 @@ namespace tunnel
|
||||
payload[-1] = 0; // zero
|
||||
ptrdiff_t paddingSize = payload - buf - 25; // 25 = 24 + 1
|
||||
if (paddingSize > 0)
|
||||
memset (buf + 24, 1, paddingSize); // padding TODO: fill with random data
|
||||
{
|
||||
// non-zero padding
|
||||
auto randomOffset = rnd.GenerateWord32 (0, TUNNEL_DATA_MAX_PAYLOAD_SIZE - paddingSize);
|
||||
memcpy (buf + 24, m_NonZeroRandomBuffer + randomOffset, paddingSize);
|
||||
}
|
||||
|
||||
// we can't fill message header yet because encryption is required
|
||||
m_TunnelDataMsgs.push_back (m_CurrentTunnelDataMsg);
|
||||
m_CurrentTunnelDataMsg = nullptr;
|
||||
}
|
||||
|
||||
|
||||
void TunnelGateway::SendTunnelDataMsg (const TunnelMessageBlock& block)
|
||||
{
|
||||
if (block.data)
|
||||
@ -192,8 +200,8 @@ namespace tunnel
|
||||
auto tunnelMsgs = m_Buffer.GetTunnelDataMsgs ();
|
||||
for (auto tunnelMsg : tunnelMsgs)
|
||||
{
|
||||
m_Tunnel->EncryptTunnelMsg (tunnelMsg);
|
||||
FillI2NPMessageHeader (tunnelMsg, eI2NPTunnelData);
|
||||
m_Tunnel->EncryptTunnelMsg (tunnelMsg, tunnelMsg);
|
||||
tunnelMsg->FillI2NPMessageHeader (eI2NPTunnelData);
|
||||
m_NumSentBytes += TUNNEL_DATA_MSG_SIZE;
|
||||
}
|
||||
i2p::transport::transports.SendMessages (m_Tunnel->GetNextIdentHash (), tunnelMsgs);
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include "I2NPProtocol.h"
|
||||
#include "TunnelBase.h"
|
||||
|
||||
@ -13,11 +14,10 @@ namespace tunnel
|
||||
class TunnelGatewayBuffer
|
||||
{
|
||||
public:
|
||||
TunnelGatewayBuffer (uint32_t tunnelID): m_TunnelID (tunnelID),
|
||||
m_CurrentTunnelDataMsg (nullptr), m_RemainingSize (0) {};
|
||||
TunnelGatewayBuffer (uint32_t tunnelID);
|
||||
~TunnelGatewayBuffer ();
|
||||
void PutI2NPMsg (const TunnelMessageBlock& block);
|
||||
const std::vector<I2NPMessage *>& GetTunnelDataMsgs () const { return m_TunnelDataMsgs; };
|
||||
const std::vector<std::shared_ptr<I2NPMessage> >& GetTunnelDataMsgs () const { return m_TunnelDataMsgs; };
|
||||
void ClearTunnelDataMsgs ();
|
||||
void CompleteCurrentTunnelDataMessage ();
|
||||
|
||||
@ -28,16 +28,17 @@ namespace tunnel
|
||||
private:
|
||||
|
||||
uint32_t m_TunnelID;
|
||||
std::vector<I2NPMessage *> m_TunnelDataMsgs;
|
||||
I2NPMessage * m_CurrentTunnelDataMsg;
|
||||
std::vector<std::shared_ptr<I2NPMessage> > m_TunnelDataMsgs;
|
||||
std::shared_ptr<I2NPMessage> m_CurrentTunnelDataMsg;
|
||||
size_t m_RemainingSize;
|
||||
uint8_t m_NonZeroRandomBuffer[TUNNEL_DATA_MAX_PAYLOAD_SIZE];
|
||||
};
|
||||
|
||||
class TunnelGateway
|
||||
{
|
||||
public:
|
||||
|
||||
TunnelGateway (TunnelBase * tunnel):
|
||||
TunnelGateway (TunnelBase * tunnel):
|
||||
m_Tunnel (tunnel), m_Buffer (tunnel->GetNextTunnelID ()), m_NumSentBytes (0) {};
|
||||
void SendTunnelDataMsg (const TunnelMessageBlock& block);
|
||||
void PutTunnelDataMsg (const TunnelMessageBlock& block);
|
||||
|
155
TunnelPool.cpp
155
TunnelPool.cpp
@ -1,3 +1,4 @@
|
||||
#include <algorithm>
|
||||
#include "I2PEndian.h"
|
||||
#include "CryptoConst.h"
|
||||
#include "Tunnel.h"
|
||||
@ -22,6 +23,27 @@ namespace tunnel
|
||||
DetachTunnels ();
|
||||
}
|
||||
|
||||
void TunnelPool::SetExplicitPeers (std::shared_ptr<std::vector<i2p::data::IdentHash> > explicitPeers)
|
||||
{
|
||||
m_ExplicitPeers = explicitPeers;
|
||||
if (m_ExplicitPeers)
|
||||
{
|
||||
int size = m_ExplicitPeers->size ();
|
||||
if (m_NumInboundHops > size)
|
||||
{
|
||||
m_NumInboundHops = size;
|
||||
LogPrint (eLogInfo, "Inbound tunnel length has beed adjusted to ", size, " for explicit peers");
|
||||
}
|
||||
if (m_NumOutboundHops > size)
|
||||
{
|
||||
m_NumOutboundHops = size;
|
||||
LogPrint (eLogInfo, "Outbound tunnel length has beed adjusted to ", size, " for explicit peers");
|
||||
}
|
||||
m_NumInboundTunnels = 1;
|
||||
m_NumOutboundTunnels = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void TunnelPool::DetachTunnels ()
|
||||
{
|
||||
{
|
||||
@ -70,7 +92,7 @@ namespace tunnel
|
||||
std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
|
||||
m_OutboundTunnels.insert (createdTunnel);
|
||||
}
|
||||
CreatePairedInboundTunnel (createdTunnel);
|
||||
//CreatePairedInboundTunnel (createdTunnel);
|
||||
}
|
||||
|
||||
void TunnelPool::TunnelExpired (std::shared_ptr<OutboundTunnel> expiredTunnel)
|
||||
@ -238,18 +260,15 @@ namespace tunnel
|
||||
}
|
||||
}
|
||||
|
||||
void TunnelPool::ProcessGarlicMessage (I2NPMessage * msg)
|
||||
void TunnelPool::ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg)
|
||||
{
|
||||
if (m_LocalDestination)
|
||||
m_LocalDestination->ProcessGarlicMessage (msg);
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "Local destination doesn't exist. Dropped");
|
||||
DeleteI2NPMessage (msg);
|
||||
}
|
||||
}
|
||||
|
||||
void TunnelPool::ProcessDeliveryStatus (I2NPMessage * msg)
|
||||
void TunnelPool::ProcessDeliveryStatus (std::shared_ptr<I2NPMessage> msg)
|
||||
{
|
||||
const uint8_t * buf = msg->GetPayload ();
|
||||
uint32_t msgID = bufbe32toh (buf);
|
||||
@ -266,17 +285,13 @@ namespace tunnel
|
||||
it->second.second->SetState (eTunnelStateEstablished);
|
||||
LogPrint ("Tunnel test ", it->first, " successive. ", i2p::util::GetMillisecondsSinceEpoch () - timestamp, " milliseconds");
|
||||
m_Tests.erase (it);
|
||||
DeleteI2NPMessage (msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_LocalDestination)
|
||||
m_LocalDestination->ProcessDeliveryStatusMessage (msg);
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "Local destination doesn't exist. Dropped");
|
||||
DeleteI2NPMessage (msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -290,41 +305,76 @@ namespace tunnel
|
||||
hop = i2p::data::netdb.GetRandomRouter ();
|
||||
return hop;
|
||||
}
|
||||
|
||||
bool TunnelPool::SelectPeers (std::vector<std::shared_ptr<const i2p::data::RouterInfo> >& hops, bool isInbound)
|
||||
{
|
||||
if (m_ExplicitPeers) return SelectExplicitPeers (hops, isInbound);
|
||||
auto prevHop = i2p::context.GetSharedRouterInfo ();
|
||||
int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops;
|
||||
if (i2p::transport::transports.GetNumPeers () > 25)
|
||||
{
|
||||
auto r = i2p::transport::transports.GetRandomPeer ();
|
||||
if (r && !r->GetProfile ()->IsBad ())
|
||||
{
|
||||
prevHop = r;
|
||||
hops.push_back (r);
|
||||
numHops--;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < numHops; i++)
|
||||
{
|
||||
auto hop = SelectNextHop (prevHop);
|
||||
if (!hop)
|
||||
{
|
||||
LogPrint (eLogError, "Can't select next hop");
|
||||
return false;
|
||||
}
|
||||
prevHop = hop;
|
||||
hops.push_back (hop);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TunnelPool::SelectExplicitPeers (std::vector<std::shared_ptr<const i2p::data::RouterInfo> >& hops, bool isInbound)
|
||||
{
|
||||
int size = m_ExplicitPeers->size ();
|
||||
std::vector<int> peerIndicies;
|
||||
for (int i = 0; i < size; i++) peerIndicies.push_back(i);
|
||||
std::random_shuffle (peerIndicies.begin(), peerIndicies.end());
|
||||
|
||||
int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops;
|
||||
for (int i = 0; i < numHops; i++)
|
||||
{
|
||||
auto& ident = (*m_ExplicitPeers)[peerIndicies[i]];
|
||||
auto r = i2p::data::netdb.FindRouter (ident);
|
||||
if (r)
|
||||
hops.push_back (r);
|
||||
else
|
||||
{
|
||||
LogPrint (eLogInfo, "Can't find router for ", ident.ToBase64 ());
|
||||
i2p::data::netdb.RequestDestination (ident);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void TunnelPool::CreateInboundTunnel ()
|
||||
{
|
||||
auto outboundTunnel = GetNextOutboundTunnel ();
|
||||
if (!outboundTunnel)
|
||||
outboundTunnel = tunnels.GetNextOutboundTunnel ();
|
||||
LogPrint ("Creating destination inbound tunnel...");
|
||||
auto prevHop = i2p::context.GetSharedRouterInfo ();
|
||||
std::vector<std::shared_ptr<const i2p::data::RouterInfo> > hops;
|
||||
int numHops = m_NumInboundHops;
|
||||
if (outboundTunnel)
|
||||
{
|
||||
// last hop
|
||||
auto hop = outboundTunnel->GetTunnelConfig ()->GetFirstHop ()->router;
|
||||
if (hop->GetIdentHash () != i2p::context.GetIdentHash ()) // outbound shouldn't be zero-hop tunnel
|
||||
{
|
||||
prevHop = hop;
|
||||
hops.push_back (prevHop);
|
||||
numHops--;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < numHops; i++)
|
||||
if (SelectPeers (hops, true))
|
||||
{
|
||||
auto hop = SelectNextHop (prevHop);
|
||||
if (!hop)
|
||||
{
|
||||
LogPrint (eLogError, "Can't select next hop for inbound tunnel");
|
||||
return;
|
||||
}
|
||||
prevHop = hop;
|
||||
hops.push_back (hop);
|
||||
}
|
||||
std::reverse (hops.begin (), hops.end ());
|
||||
auto tunnel = tunnels.CreateTunnel<InboundTunnel> (std::make_shared<TunnelConfig> (hops), outboundTunnel);
|
||||
tunnel->SetTunnelPool (shared_from_this ());
|
||||
std::reverse (hops.begin (), hops.end ());
|
||||
auto tunnel = tunnels.CreateTunnel<InboundTunnel> (std::make_shared<TunnelConfig> (hops), outboundTunnel);
|
||||
tunnel->SetTunnelPool (shared_from_this ());
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "Can't create inbound tunnel. No peers available");
|
||||
}
|
||||
|
||||
void TunnelPool::RecreateInboundTunnel (std::shared_ptr<InboundTunnel> tunnel)
|
||||
@ -345,34 +395,15 @@ namespace tunnel
|
||||
if (inboundTunnel)
|
||||
{
|
||||
LogPrint ("Creating destination outbound tunnel...");
|
||||
int numHops = m_NumOutboundHops;
|
||||
auto prevHop = i2p::context.GetSharedRouterInfo ();
|
||||
std::vector<std::shared_ptr<const i2p::data::RouterInfo> > hops;
|
||||
if (i2p::transport::transports.GetNumPeers () > 25)
|
||||
{
|
||||
auto r = i2p::transport::transports.GetRandomPeer ();
|
||||
if (r)
|
||||
{
|
||||
prevHop = r;
|
||||
hops.push_back (r);
|
||||
numHops--;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < numHops; i++)
|
||||
{
|
||||
auto hop = SelectNextHop (prevHop);
|
||||
if (!hop)
|
||||
{
|
||||
LogPrint (eLogError, "Can't select next hop for outbound tunnel");
|
||||
return;
|
||||
}
|
||||
prevHop = hop;
|
||||
hops.push_back (hop);
|
||||
if (SelectPeers (hops, false))
|
||||
{
|
||||
auto tunnel = tunnels.CreateTunnel<OutboundTunnel> (
|
||||
std::make_shared<TunnelConfig> (hops, inboundTunnel->GetTunnelConfig ()));
|
||||
tunnel->SetTunnelPool (shared_from_this ());
|
||||
}
|
||||
|
||||
auto tunnel = tunnels.CreateTunnel<OutboundTunnel> (
|
||||
std::make_shared<TunnelConfig> (hops, inboundTunnel->GetTunnelConfig ()));
|
||||
tunnel->SetTunnelPool (shared_from_this ());
|
||||
else
|
||||
LogPrint (eLogError, "Can't create outbound tunnel. No peers available");
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "Can't create outbound tunnel. No inbound tunnels found");
|
||||
|
10
TunnelPool.h
10
TunnelPool.h
@ -32,6 +32,7 @@ namespace tunnel
|
||||
|
||||
i2p::garlic::GarlicDestination * GetLocalDestination () const { return m_LocalDestination; };
|
||||
void SetLocalDestination (i2p::garlic::GarlicDestination * destination) { m_LocalDestination = destination; };
|
||||
void SetExplicitPeers (std::shared_ptr<std::vector<i2p::data::IdentHash> > explicitPeers);
|
||||
|
||||
void CreateTunnels ();
|
||||
void TunnelCreated (std::shared_ptr<InboundTunnel> createdTunnel);
|
||||
@ -46,8 +47,8 @@ namespace tunnel
|
||||
std::shared_ptr<OutboundTunnel> GetNewOutboundTunnel (std::shared_ptr<OutboundTunnel> old) const;
|
||||
|
||||
void TestTunnels ();
|
||||
void ProcessGarlicMessage (I2NPMessage * msg);
|
||||
void ProcessDeliveryStatus (I2NPMessage * msg);
|
||||
void ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg);
|
||||
void ProcessDeliveryStatus (std::shared_ptr<I2NPMessage> msg);
|
||||
|
||||
bool IsActive () const { return m_IsActive; };
|
||||
void SetActive (bool isActive) { m_IsActive = isActive; };
|
||||
@ -61,11 +62,14 @@ namespace tunnel
|
||||
template<class TTunnels>
|
||||
typename TTunnels::value_type GetNextTunnel (TTunnels& tunnels, typename TTunnels::value_type excluded) const;
|
||||
std::shared_ptr<const i2p::data::RouterInfo> SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop) const;
|
||||
|
||||
bool SelectPeers (std::vector<std::shared_ptr<const i2p::data::RouterInfo> >& hops, bool isInbound);
|
||||
bool SelectExplicitPeers (std::vector<std::shared_ptr<const i2p::data::RouterInfo> >& hops, bool isInbound);
|
||||
|
||||
private:
|
||||
|
||||
i2p::garlic::GarlicDestination * m_LocalDestination;
|
||||
int m_NumInboundHops, m_NumOutboundHops, m_NumInboundTunnels, m_NumOutboundTunnels;
|
||||
std::shared_ptr<std::vector<i2p::data::IdentHash> > m_ExplicitPeers;
|
||||
mutable std::mutex m_InboundTunnelsMutex;
|
||||
std::set<std::shared_ptr<InboundTunnel>, TunnelCreationTimeCmp> m_InboundTunnels; // recent tunnel appears first
|
||||
mutable std::mutex m_OutboundTunnelsMutex;
|
||||
|
142
UPnP.cpp
142
UPnP.cpp
@ -2,15 +2,19 @@
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#define dlsym GetProcAddress
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include "Log.h"
|
||||
|
||||
#include "RouterContext.h"
|
||||
#include "UPnP.h"
|
||||
#include "NetDb.h"
|
||||
@ -18,24 +22,36 @@
|
||||
|
||||
#include <miniupnpc/miniupnpc.h>
|
||||
#include <miniupnpc/upnpcommands.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
// These are per-process and are safe to reuse for all threads
|
||||
#ifndef UPNPDISCOVER_SUCCESS
|
||||
/* miniupnpc 1.5 */
|
||||
typedef UPNPDev* (*upnp_upnpDiscoverFunc) (int, const char *, const char *, int);
|
||||
typedef int (*upnp_UPNP_AddPortMappingFunc) (const char *, const char *, const char *, const char *,
|
||||
UPNPDev* (*upnpDiscoverFunc) (int, const char *, const char *, int);
|
||||
int (*UPNP_AddPortMappingFunc) (const char *, const char *, const char *, const char *,
|
||||
const char *, const char *, const char *, const char *);
|
||||
#else
|
||||
/* miniupnpc 1.6 */
|
||||
typedef UPNPDev* (*upnp_upnpDiscoverFunc) (int, const char *, const char *, int, int, int *);
|
||||
typedef int (*upnp_UPNP_AddPortMappingFunc) (const char *, const char *, const char *, const char *,
|
||||
UPNPDev* (*upnpDiscoverFunc) (int, const char *, const char *, int, int, int *);
|
||||
int (*UPNP_AddPortMappingFunc) (const char *, const char *, const char *, const char *,
|
||||
const char *, const char *, const char *, const char *, const char *);
|
||||
#endif
|
||||
typedef int (*upnp_UPNP_GetValidIGDFunc) (struct UPNPDev *, struct UPNPUrls *, struct IGDdatas *, char *, int);
|
||||
typedef int (*upnp_UPNP_GetExternalIPAddressFunc) (const char *, const char *, char *);
|
||||
typedef int (*upnp_UPNP_DeletePortMappingFunc) (const char *, const char *, const char *, const char *, const char *);
|
||||
typedef void (*upnp_freeUPNPDevlistFunc) (struct UPNPDev *);
|
||||
typedef void (*upnp_FreeUPNPUrlsFunc) (struct UPNPUrls *);
|
||||
int (*UPNP_GetValidIGDFunc) (struct UPNPDev *, struct UPNPUrls *, struct IGDdatas *, char *, int);
|
||||
int (*UPNP_GetExternalIPAddressFunc) (const char *, const char *, char *);
|
||||
int (*UPNP_DeletePortMappingFunc) (const char *, const char *, const char *, const char *, const char *);
|
||||
void (*freeUPNPDevlistFunc) (struct UPNPDev *);
|
||||
void (*FreeUPNPUrlsFunc) (struct UPNPUrls *);
|
||||
|
||||
// Nice approach http://stackoverflow.com/a/21517513/673826
|
||||
template<class M, typename F>
|
||||
F GetKnownProcAddressImpl(M hmod, const char *name, F) {
|
||||
auto proc = reinterpret_cast<F>(dlsym(hmod, name));
|
||||
if (!proc) {
|
||||
LogPrint("Error resolving ", name, " from UPNP library. This often happens if there is version mismatch!");
|
||||
}
|
||||
return proc;
|
||||
}
|
||||
#define GetKnownProcAddress(hmod, func) GetKnownProcAddressImpl(hmod, #func, func##Func);
|
||||
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
@ -57,6 +73,33 @@ namespace transport
|
||||
|
||||
void UPnP::Start()
|
||||
{
|
||||
if (!m_IsModuleLoaded) {
|
||||
#ifdef MAC_OSX
|
||||
m_Module = dlopen ("libminiupnpc.dylib", RTLD_LAZY);
|
||||
#elif _WIN32
|
||||
m_Module = LoadLibrary ("miniupnpc.dll"); // official prebuilt binary, e.g., in upnpc-exe-win32-20140422.zip
|
||||
#else
|
||||
m_Module = dlopen ("libminiupnpc.so", RTLD_LAZY);
|
||||
#endif
|
||||
if (m_Module == NULL)
|
||||
{
|
||||
LogPrint ("Error loading UPNP library. This often happens if there is version mismatch!");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
upnpDiscoverFunc = GetKnownProcAddress (m_Module, upnpDiscover);
|
||||
UPNP_GetValidIGDFunc = GetKnownProcAddress (m_Module, UPNP_GetValidIGD);
|
||||
UPNP_GetExternalIPAddressFunc = GetKnownProcAddress (m_Module, UPNP_GetExternalIPAddress);
|
||||
UPNP_AddPortMappingFunc = GetKnownProcAddress (m_Module, UPNP_AddPortMapping);
|
||||
UPNP_DeletePortMappingFunc = GetKnownProcAddress (m_Module, UPNP_DeletePortMapping);
|
||||
freeUPNPDevlistFunc = GetKnownProcAddress (m_Module, freeUPNPDevlist);
|
||||
FreeUPNPUrlsFunc = GetKnownProcAddress (m_Module, FreeUPNPUrls);
|
||||
if (upnpDiscoverFunc && UPNP_GetValidIGDFunc && UPNP_GetExternalIPAddressFunc && UPNP_AddPortMappingFunc &&
|
||||
UPNP_DeletePortMappingFunc && freeUPNPDevlistFunc && FreeUPNPUrlsFunc)
|
||||
m_IsModuleLoaded = true;
|
||||
}
|
||||
}
|
||||
m_Thread = new std::thread (std::bind (&UPnP::Run, this));
|
||||
}
|
||||
|
||||
@ -66,33 +109,6 @@ namespace transport
|
||||
|
||||
void UPnP::Run ()
|
||||
{
|
||||
#ifdef MAC_OSX
|
||||
m_Module = dlopen ("libminiupnpc.dylib", RTLD_LAZY);
|
||||
#elif _WIN32
|
||||
m_Module = LoadLibrary ("libminiupnpc.dll");
|
||||
if (m_Module == NULL)
|
||||
{
|
||||
LogPrint ("Error loading UPNP library. This often happens if there is version mismatch!");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_IsModuleLoaded = true;
|
||||
}
|
||||
#else
|
||||
m_Module = dlopen ("libminiupnpc.so", RTLD_LAZY);
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
if (!m_Module)
|
||||
{
|
||||
LogPrint ("no UPnP module available (", dlerror (), ")");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_IsModuleLoaded = true;
|
||||
}
|
||||
#endif
|
||||
for (auto& address : context.GetRouterInfo ().GetAddresses ())
|
||||
{
|
||||
if (!address.host.is_v6 ())
|
||||
@ -112,18 +128,6 @@ namespace transport
|
||||
|
||||
void UPnP::Discover ()
|
||||
{
|
||||
const char *error;
|
||||
#ifdef _WIN32
|
||||
upnp_upnpDiscoverFunc upnpDiscoverFunc = (upnp_upnpDiscoverFunc) GetProcAddress (m_Module, "upnpDiscover");
|
||||
#else
|
||||
upnp_upnpDiscoverFunc upnpDiscoverFunc = (upnp_upnpDiscoverFunc) dlsym (m_Module, "upnpDiscover");
|
||||
// reinterpret_cast<upnp_upnpDiscoverFunc> (dlsym(...));
|
||||
if ( (error = dlerror ()))
|
||||
{
|
||||
LogPrint ("Error loading UPNP library. This often happens if there is version mismatch!");
|
||||
return;
|
||||
}
|
||||
#endif // _WIN32
|
||||
#ifndef UPNPDISCOVER_SUCCESS
|
||||
/* miniupnpc 1.5 */
|
||||
m_Devlist = upnpDiscoverFunc (2000, m_MulticastIf, m_Minissdpdpath, 0);
|
||||
@ -134,15 +138,9 @@ namespace transport
|
||||
#endif
|
||||
|
||||
int r;
|
||||
#ifdef _WIN32
|
||||
upnp_UPNP_GetValidIGDFunc UPNP_GetValidIGDFunc = (upnp_UPNP_GetValidIGDFunc) GetProcAddress (m_Module, "UPNP_GetValidIGD");
|
||||
#else
|
||||
upnp_UPNP_GetValidIGDFunc UPNP_GetValidIGDFunc = (upnp_UPNP_GetValidIGDFunc) dlsym (m_Module, "UPNP_GetValidIGD");
|
||||
#endif
|
||||
r = (*UPNP_GetValidIGDFunc) (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr));
|
||||
r = UPNP_GetValidIGDFunc (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr));
|
||||
if (r == 1)
|
||||
{
|
||||
upnp_UPNP_GetExternalIPAddressFunc UPNP_GetExternalIPAddressFunc = (upnp_UPNP_GetExternalIPAddressFunc) dlsym (m_Module, "UPNP_GetExternalIPAddress");
|
||||
r = UPNP_GetExternalIPAddressFunc (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
|
||||
if(r != UPNPCOMMAND_SUCCESS)
|
||||
{
|
||||
@ -182,11 +180,6 @@ namespace transport
|
||||
std::string strDesc = "I2Pd";
|
||||
try {
|
||||
for (;;) {
|
||||
#ifdef _WIN32
|
||||
upnp_UPNP_AddPortMappingFunc UPNP_AddPortMappingFunc = (upnp_UPNP_AddPortMappingFunc) GetProcAddress (m_Module, "UPNP_AddPortMapping");
|
||||
#else
|
||||
upnp_UPNP_AddPortMappingFunc UPNP_AddPortMappingFunc = (upnp_UPNP_AddPortMappingFunc) dlsym (m_Module, "UPNP_AddPortMapping");
|
||||
#endif
|
||||
#ifndef UPNPDISCOVER_SUCCESS
|
||||
/* miniupnpc 1.5 */
|
||||
r = UPNP_AddPortMappingFunc (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), 0);
|
||||
@ -204,7 +197,9 @@ namespace transport
|
||||
LogPrint ("UPnP Port Mapping successful. (", m_NetworkAddr ,":", strPort.c_str(), " type ", strType.c_str () ," -> ", m_externalIPAddress ,":", strPort.c_str() ,")");
|
||||
return;
|
||||
}
|
||||
sleep(20*60);
|
||||
std::this_thread::sleep_for(std::chrono::minutes(20)); // c++11
|
||||
//boost::this_thread::sleep_for(); // pre c++11
|
||||
//sleep(20*60); // non-portable
|
||||
}
|
||||
}
|
||||
catch (boost::thread_interrupted)
|
||||
@ -228,29 +223,14 @@ namespace transport
|
||||
strType = "UDP";
|
||||
}
|
||||
int r = 0;
|
||||
#ifdef _WIN32
|
||||
upnp_UPNP_DeletePortMappingFunc UPNP_DeletePortMappingFunc = (upnp_UPNP_DeletePortMappingFunc) GetProcAddress (m_Module, "UPNP_DeletePortMapping");
|
||||
#else
|
||||
upnp_UPNP_DeletePortMappingFunc UPNP_DeletePortMappingFunc = (upnp_UPNP_DeletePortMappingFunc) dlsym (m_Module, "UPNP_DeletePortMapping");
|
||||
#endif
|
||||
r = UPNP_DeletePortMappingFunc (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strType.c_str (), 0);
|
||||
LogPrint ("UPNP_DeletePortMapping() returned : ", r, "\n");
|
||||
}
|
||||
|
||||
void UPnP::Close ()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
upnp_freeUPNPDevlistFunc freeUPNPDevlistFunc = (upnp_freeUPNPDevlistFunc) GetProcAddress (m_Module, "freeUPNPDevlist");
|
||||
#else
|
||||
upnp_freeUPNPDevlistFunc freeUPNPDevlistFunc = (upnp_freeUPNPDevlistFunc) dlsym (m_Module, "freeUPNPDevlist");
|
||||
#endif
|
||||
freeUPNPDevlistFunc (m_Devlist);
|
||||
m_Devlist = 0;
|
||||
#ifdef _WIN32
|
||||
upnp_FreeUPNPUrlsFunc FreeUPNPUrlsFunc = (upnp_FreeUPNPUrlsFunc) GetProcAddress (m_Module, "FreeUPNPUrlsFunc");
|
||||
#else
|
||||
upnp_FreeUPNPUrlsFunc FreeUPNPUrlsFunc = (upnp_FreeUPNPUrlsFunc) dlsym (m_Module, "FreeUPNPUrlsFunc");
|
||||
#endif
|
||||
FreeUPNPUrlsFunc (&m_upnpUrls);
|
||||
#ifndef _WIN32
|
||||
dlclose (m_Module);
|
||||
|
2
UPnP.h
2
UPnP.h
@ -52,7 +52,7 @@ namespace transport
|
||||
#ifndef _WIN32
|
||||
void *m_Module;
|
||||
#else
|
||||
HINSTANCE *m_Module;
|
||||
HINSTANCE m_Module;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
@ -3,8 +3,8 @@ Building i2pd for Windows
|
||||
|
||||
Requirements for building:
|
||||
|
||||
* Visual Studio 2013 (tested with VS2013 Update 1, Update 3, and Update 4 RC)
|
||||
* Boost (tested with 1.56 and 1.57)
|
||||
* Visual Studio 2013 (tested with VS2013 Update 1, Update 3, and Update 4)
|
||||
* Boost (tested with 1.56, 1.57, and 1.58)
|
||||
* Crypto++ (tested with 5.6.2)
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@ After Boost is compiled, set the environment variable `BOOST` to the directory
|
||||
Boost was installed to. If you followed the instructions outlined here, you
|
||||
should set it to `C:\Boost`. Additionally, set the BOOSTVER variable to the
|
||||
version of Boost that you're using, but instead of a '.' use a '_'. For
|
||||
example, I have `BOOSTVER` set to `1_57`.
|
||||
example, I have `BOOSTVER` set to `1_58`.
|
||||
|
||||
Building Crypto++
|
||||
-----------------
|
||||
|
46
aes.cpp
46
aes.cpp
@ -280,74 +280,76 @@ namespace crypto
|
||||
#endif
|
||||
}
|
||||
|
||||
void TunnelEncryption::Encrypt (uint8_t * payload)
|
||||
void TunnelEncryption::Encrypt (const uint8_t * in, uint8_t * out)
|
||||
{
|
||||
#ifdef AESNI
|
||||
__asm__
|
||||
(
|
||||
// encrypt IV
|
||||
"movups (%[payload]), %%xmm0 \n"
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
EncryptAES256(sched_iv)
|
||||
"movaps %%xmm0, %%xmm1 \n"
|
||||
// double IV encryption
|
||||
EncryptAES256(sched_iv)
|
||||
"movups %%xmm0, (%[payload]) \n"
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
// encrypt data, IV is xmm1
|
||||
"1: \n"
|
||||
"add $16, %[payload] \n"
|
||||
"movups (%[payload]), %%xmm0 \n"
|
||||
"add $16, %[in] \n"
|
||||
"add $16, %[out] \n"
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
"pxor %%xmm1, %%xmm0 \n"
|
||||
EncryptAES256(sched_l)
|
||||
"movaps %%xmm0, %%xmm1 \n"
|
||||
"movups %%xmm0, (%[payload]) \n"
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
"dec %[num] \n"
|
||||
"jnz 1b \n"
|
||||
:
|
||||
: [sched_iv]"r"(m_IVEncryption.GetKeySchedule ()), [sched_l]"r"(m_LayerEncryption.GetKeySchedule ()),
|
||||
[payload]"r"(payload), [num]"r"(63) // 63 blocks = 1008 bytes
|
||||
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
|
||||
: "%xmm0", "%xmm1", "cc", "memory"
|
||||
);
|
||||
#else
|
||||
m_IVEncryption.Encrypt ((ChipherBlock *)payload, (ChipherBlock *)payload); // iv
|
||||
m_LayerEncryption.SetIV (payload);
|
||||
m_LayerEncryption.Encrypt (payload + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, payload + 16); // data
|
||||
m_IVEncryption.Encrypt ((ChipherBlock *)payload, (ChipherBlock *)payload); // double iv
|
||||
m_IVEncryption.Encrypt ((const ChipherBlock *)in, (ChipherBlock *)out); // iv
|
||||
m_LayerEncryption.SetIV (out);
|
||||
m_LayerEncryption.Encrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, out + 16); // data
|
||||
m_IVEncryption.Encrypt ((ChipherBlock *)out, (ChipherBlock *)out); // double iv
|
||||
#endif
|
||||
}
|
||||
|
||||
void TunnelDecryption::Decrypt (uint8_t * payload)
|
||||
void TunnelDecryption::Decrypt (const uint8_t * in, uint8_t * out)
|
||||
{
|
||||
#ifdef AESNI
|
||||
__asm__
|
||||
(
|
||||
// decrypt IV
|
||||
"movups (%[payload]), %%xmm0 \n"
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
DecryptAES256(sched_iv)
|
||||
"movaps %%xmm0, %%xmm1 \n"
|
||||
// double IV encryption
|
||||
DecryptAES256(sched_iv)
|
||||
"movups %%xmm0, (%[payload]) \n"
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
// decrypt data, IV is xmm1
|
||||
"1: \n"
|
||||
"add $16, %[payload] \n"
|
||||
"movups (%[payload]), %%xmm0 \n"
|
||||
"add $16, %[in] \n"
|
||||
"add $16, %[out] \n"
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
"movaps %%xmm0, %%xmm2 \n"
|
||||
DecryptAES256(sched_l)
|
||||
"pxor %%xmm1, %%xmm0 \n"
|
||||
"movups %%xmm0, (%[payload]) \n"
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
"movaps %%xmm2, %%xmm1 \n"
|
||||
"dec %[num] \n"
|
||||
"jnz 1b \n"
|
||||
:
|
||||
: [sched_iv]"r"(m_IVDecryption.GetKeySchedule ()), [sched_l]"r"(m_LayerDecryption.GetKeySchedule ()),
|
||||
[payload]"r"(payload), [num]"r"(63) // 63 blocks = 1008 bytes
|
||||
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
|
||||
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
|
||||
);
|
||||
#else
|
||||
m_IVDecryption.Decrypt ((ChipherBlock *)payload, (ChipherBlock *)payload); // iv
|
||||
m_LayerDecryption.SetIV (payload);
|
||||
m_LayerDecryption.Decrypt (payload + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, payload + 16); // data
|
||||
m_IVDecryption.Decrypt ((ChipherBlock *)payload, (ChipherBlock *)payload); // double iv
|
||||
m_IVDecryption.Decrypt ((const ChipherBlock *)in, (ChipherBlock *)out); // iv
|
||||
m_LayerDecryption.SetIV (out);
|
||||
m_LayerDecryption.Decrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, out + 16); // data
|
||||
m_IVDecryption.Decrypt ((ChipherBlock *)out, (ChipherBlock *)out); // double iv
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
4
aes.h
4
aes.h
@ -185,7 +185,7 @@ namespace crypto
|
||||
m_IVEncryption.SetKey (ivKey);
|
||||
}
|
||||
|
||||
void Encrypt (uint8_t * payload); // 1024 bytes (16 IV + 1008 data)
|
||||
void Encrypt (const uint8_t * in, uint8_t * out); // 1024 bytes (16 IV + 1008 data)
|
||||
|
||||
private:
|
||||
|
||||
@ -207,7 +207,7 @@ namespace crypto
|
||||
m_IVDecryption.SetKey (ivKey);
|
||||
}
|
||||
|
||||
void Decrypt (uint8_t * payload); // 1024 bytes (16 IV + 1008 data)
|
||||
void Decrypt (const uint8_t * in, uint8_t * out); // 1024 bytes (16 IV + 1008 data)
|
||||
|
||||
private:
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
cmake_minimum_required ( VERSION 2.8.5 )
|
||||
cmake_minimum_required ( VERSION 2.8.12 )
|
||||
project ( "i2pd" )
|
||||
|
||||
# configurale options
|
||||
@ -7,6 +7,8 @@ option(WITH_HARDENING "Use hardening compiler flags" OFF)
|
||||
option(WITH_LIBRARY "Build library" ON)
|
||||
option(WITH_BINARY "Build binary" ON)
|
||||
option(WITH_STATIC "Static build" OFF)
|
||||
option(WITH_UPNP "Include support for UPnP client" OFF)
|
||||
option(WITH_PCH "Use precompiled header" OFF)
|
||||
|
||||
# paths
|
||||
set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules" )
|
||||
@ -43,8 +45,13 @@ set (COMMON_SRC
|
||||
"${CMAKE_SOURCE_DIR}/util.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/Datagram.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/Signature.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/UPnP.cpp"
|
||||
)
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
list (APPEND COMMON_SRC "${CMAKE_SOURCE_DIR}/I2PEndian.cpp")
|
||||
endif ()
|
||||
|
||||
add_library(common ${COMMON_SRC})
|
||||
|
||||
set (DAEMON_SRC
|
||||
@ -58,10 +65,16 @@ set (DAEMON_SRC
|
||||
"${CMAKE_SOURCE_DIR}/I2PTunnel.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/SAM.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/SOCKS.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/UPnP.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/i2p.cpp"
|
||||
)
|
||||
|
||||
if (WITH_UPNP)
|
||||
add_definitions(-DUSE_UPNP)
|
||||
if (NOT MSVC)
|
||||
set(DL_LIB ${CMAKE_DL_LIBS})
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
set (LIBRARY_SRC
|
||||
"${CMAKE_SOURCE_DIR}/api.cpp"
|
||||
)
|
||||
@ -73,14 +86,19 @@ source_group ("Header Files" FILES ${HEADERS})
|
||||
source_group ("Source Files" FILES ${COMMON_SRC} ${DAEMON_SRC} ${LIBRARY_SRC})
|
||||
|
||||
# Default build is Debug
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
add_definitions( "-pedantic" )
|
||||
else ()
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
endif ()
|
||||
|
||||
# compiler flags customization (by vendor)
|
||||
add_definitions ( "-Wall -Wextra -fPIC" )
|
||||
if (NOT MSVC)
|
||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Winvalid-pch" )
|
||||
set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pedantic" )
|
||||
# TODO: The following is incompatible with static build and enabled hardening for OpenWRT.
|
||||
# Multiple definitions of __stack_chk_fail (libssp & libc)
|
||||
set( CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -flto -s -ffunction-sections -fdata-sections" )
|
||||
set( CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-Wl,--gc-sections" ) # -flto is added from above
|
||||
endif ()
|
||||
|
||||
# check for c++11 support
|
||||
include(CheckCXXCompilerFlag)
|
||||
@ -90,7 +108,7 @@ if (CXX11_SUPPORTED)
|
||||
add_definitions( "-std=c++11" )
|
||||
elseif (CXX0X_SUPPORTED) # gcc 4.6
|
||||
add_definitions( "-std=c++0x" )
|
||||
else ()
|
||||
elseif (NOT MSVC)
|
||||
message(SEND_ERROR "C++11 standart not seems to be supported by compiler. Too old version?")
|
||||
endif ()
|
||||
|
||||
@ -117,6 +135,7 @@ elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
list (APPEND DAEMON_SRC "${CMAKE_SOURCE_DIR}/DaemonLinux.cpp")
|
||||
elseif (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
list (APPEND DAEMON_SRC "${CMAKE_SOURCE_DIR}/DaemonWin32.cpp")
|
||||
list (APPEND DAEMON_SRC "${CMAKE_SOURCE_DIR}/Win32/Win32Service.cpp")
|
||||
endif ()
|
||||
|
||||
if (WITH_AESNI)
|
||||
@ -124,9 +143,71 @@ if (WITH_AESNI)
|
||||
endif()
|
||||
|
||||
# libraries
|
||||
# TODO: once CMake 3.1+ becomes mainstream, see e.g. http://stackoverflow.com/a/29871891/673826
|
||||
# use imported Threads::Threads instead
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package ( Threads REQUIRED )
|
||||
if(THREADS_HAVE_PTHREAD_ARG) # compile time flag
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
|
||||
endif()
|
||||
|
||||
find_package ( Boost COMPONENTS system filesystem regex program_options date_time REQUIRED )
|
||||
if (WITH_STATIC)
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
set(Boost_USE_STATIC_RUNTIME ON)
|
||||
if (WIN32)
|
||||
# http://www.cmake.org/Wiki/CMake_FAQ#Dynamic_Replace
|
||||
# Note that you might need to rebuild Crypto++
|
||||
foreach(flag_var
|
||||
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
|
||||
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
|
||||
if(${flag_var} MATCHES "/MD")
|
||||
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
|
||||
endif(${flag_var} MATCHES "/MD")
|
||||
endforeach(flag_var)
|
||||
else ()
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
|
||||
endif ()
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
if (${CMAKE_CXX_COMPILER} MATCHES ".*-openwrt-.*")
|
||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread" )
|
||||
# set( CMAKE_THREAD_LIBS_INIT "gcc_eh -Wl,--whole-archive -lpthread -Wl,--no-whole-archive" )
|
||||
set( CMAKE_THREAD_LIBS_INIT "gcc_eh -Wl,-u,pthread_create,-u,pthread_once,-u,pthread_mutex_lock,-u,pthread_mutex_unlock,-u,pthread_join,-u,pthread_equal,-u,pthread_detach,-u,pthread_cond_wait,-u,pthread_cond_signal,-u,pthread_cond_destroy,-u,pthread_cond_broadcast,-u,pthread_cancel" )
|
||||
endif ()
|
||||
else()
|
||||
if (NOT WIN32)
|
||||
# TODO: Consider separate compilation for COMMON_SRC for library.
|
||||
# No need in -fPIC overhead for binary if not interested in library
|
||||
# HINT: revert c266cff CMakeLists.txt: compilation speed up
|
||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC" )
|
||||
endif ()
|
||||
add_definitions(-DBOOST_ALL_DYN_LINK)
|
||||
endif ()
|
||||
|
||||
if (WITH_PCH)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
|
||||
add_library(stdafx STATIC "${CMAKE_SOURCE_DIR}/stdafx.cpp")
|
||||
if(MSVC)
|
||||
target_compile_options(stdafx PRIVATE /Ycstdafx.h /Zm135)
|
||||
add_custom_command(TARGET stdafx POST_BUILD
|
||||
COMMAND xcopy /y stdafx.dir\\$<CONFIG>\\*.pdb common.dir\\$<CONFIG>\\
|
||||
COMMAND xcopy /y stdafx.dir\\$<CONFIG>\\*.pdb i2pd-bin.dir\\$<CONFIG>\\
|
||||
COMMAND xcopy /y stdafx.dir\\$<CONFIG>\\*.pdb i2pd.dir\\$<CONFIG>\\
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
target_compile_options(common PRIVATE /FIstdafx.h /Yustdafx.h /Zm135 "/Fp${CMAKE_BINARY_DIR}/stdafx.dir/$<CONFIG>/stdafx.pch")
|
||||
else()
|
||||
string(TOUPPER ${CMAKE_BUILD_TYPE} BTU)
|
||||
get_directory_property(DEFS DEFINITIONS)
|
||||
string(REPLACE " " ";" FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BTU}} ${DEFS}")
|
||||
add_custom_command(TARGET stdafx PRE_BUILD
|
||||
COMMAND ${CMAKE_CXX_COMPILER} ${FLAGS} -c ${CMAKE_CURRENT_SOURCE_DIR}/../stdafx.h
|
||||
)
|
||||
target_compile_options(common PRIVATE -include stdafx.h)
|
||||
endif()
|
||||
target_link_libraries(common stdafx)
|
||||
endif()
|
||||
|
||||
find_package ( Boost COMPONENTS system filesystem regex program_options date_time thread chrono REQUIRED )
|
||||
if(NOT DEFINED Boost_INCLUDE_DIRS)
|
||||
message(SEND_ERROR "Boost is not found, or your boost version was bellow 1.46. Please download Boost!")
|
||||
endif()
|
||||
@ -136,8 +217,13 @@ if(NOT DEFINED CRYPTO++_INCLUDE_DIR)
|
||||
message(SEND_ERROR "Could not find Crypto++. Please download and install it first!")
|
||||
endif()
|
||||
|
||||
find_package ( MiniUPnPc )
|
||||
if (NOT ${MINIUPNPC_FOUND})
|
||||
set(WITH_UPNP OFF)
|
||||
endif()
|
||||
|
||||
# load includes
|
||||
include_directories( ${Boost_INCLUDE_DIRS} ${CRYPTO++_INCLUDE_DIR} "${CMAKE_SOURCE_DIR}/..")
|
||||
include_directories( ${Boost_INCLUDE_DIRS} ${CRYPTO++_INCLUDE_DIR} )
|
||||
|
||||
# show summary
|
||||
message(STATUS "---------------------------------------")
|
||||
@ -152,6 +238,8 @@ message(STATUS " HARDENING : ${WITH_HARDENING}")
|
||||
message(STATUS " LIBRARY : ${WITH_LIBRARY}")
|
||||
message(STATUS " BINARY : ${WITH_BINARY}")
|
||||
message(STATUS " STATIC BUILD : ${WITH_STATIC}")
|
||||
message(STATUS " UPnP : ${WITH_UPNP}")
|
||||
message(STATUS " PCH : ${WITH_PCH}")
|
||||
message(STATUS "---------------------------------------")
|
||||
|
||||
#Handle paths nicely
|
||||
@ -159,24 +247,53 @@ include(GNUInstallDirs)
|
||||
|
||||
if (WITH_BINARY)
|
||||
add_executable ( "${PROJECT_NAME}-bin" ${DAEMON_SRC} )
|
||||
if(NOT MSVC) # FIXME: incremental linker file name (.ilk) collision for dll & exe
|
||||
set_target_properties("${PROJECT_NAME}-bin" PROPERTIES OUTPUT_NAME "${PROJECT_NAME}")
|
||||
if (WITH_STATIC)
|
||||
set_target_properties("${PROJECT_NAME}-bin" PROPERTIES LINK_FLAGS "-static" )
|
||||
endif ()
|
||||
endif()
|
||||
|
||||
if (WITH_PCH)
|
||||
if (MSVC)
|
||||
target_compile_options("${PROJECT_NAME}-bin" PRIVATE /FIstdafx.h /Yustdafx.h /Zm135 "/Fp${CMAKE_BINARY_DIR}/stdafx.dir/$<CONFIG>/stdafx.pch")
|
||||
else()
|
||||
target_compile_options("${PROJECT_NAME}-bin" PRIVATE -include stdafx.h)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (WITH_HARDENING AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set_target_properties("${PROJECT_NAME}-bin" PROPERTIES LINK_FLAGS "-z relro -z now" )
|
||||
endif ()
|
||||
|
||||
if (WITH_STATIC)
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
set_target_properties("${PROJECT_NAME}-bin" PROPERTIES LINK_FLAGS "-static" )
|
||||
endif ()
|
||||
|
||||
target_link_libraries( "${PROJECT_NAME}-bin" common ${Boost_LIBRARIES} ${CRYPTO++_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} )
|
||||
# FindBoost pulls pthread for thread which is broken for static linking at least on Ubuntu 15.04
|
||||
list(GET Boost_LIBRARIES -1 LAST_Boost_LIBRARIES)
|
||||
if(${LAST_Boost_LIBRARIES} MATCHES ".*pthread.*")
|
||||
list(REMOVE_AT Boost_LIBRARIES -1)
|
||||
endif()
|
||||
target_link_libraries( "${PROJECT_NAME}-bin" common ${DL_LIB} ${Boost_LIBRARIES} ${CRYPTO++_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} )
|
||||
|
||||
install(TARGETS "${PROJECT_NAME}-bin" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} )
|
||||
if (MSVC)
|
||||
install(FILES $<TARGET_PDB_FILE:${PROJECT_NAME}-bin> DESTINATION "bin" CONFIGURATIONS DEBUG)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (WITH_LIBRARY)
|
||||
add_library(${PROJECT_NAME} SHARED ${LIBRARY_SRC})
|
||||
target_link_libraries( ${PROJECT_NAME} common )
|
||||
install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} )
|
||||
if (MSVC)
|
||||
# FIXME: DLL would not have any symbols unless we use __declspec(dllexport) through out the code
|
||||
add_library(${PROJECT_NAME} STATIC ${LIBRARY_SRC})
|
||||
else ()
|
||||
add_library(${PROJECT_NAME} ${LIBRARY_SRC})
|
||||
target_link_libraries( ${PROJECT_NAME} common ${Boost_LIBRARIES} ${CRYPTO++_LIBRARIES})
|
||||
endif ()
|
||||
if (WITH_PCH)
|
||||
if (MSVC)
|
||||
add_dependencies(${PROJECT_NAME} stdafx)
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE /FIstdafx.h /Yustdafx.h /Zm135 "/Fp${CMAKE_BINARY_DIR}/stdafx.dir/$<CONFIG>/stdafx.pch")
|
||||
else()
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE -include stdafx.h)
|
||||
endif()
|
||||
endif()
|
||||
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif ()
|
||||
|
@ -4,14 +4,14 @@ if(CRYPTO++_INCLUDE_DIR AND CRYPTO++_LIBRARIES)
|
||||
set(CRYPTO++_FOUND TRUE)
|
||||
|
||||
else(CRYPTO++_INCLUDE_DIR AND CRYPTO++_LIBRARIES)
|
||||
find_path(CRYPTO++_INCLUDE_DIR cryptlib.h
|
||||
/usr/include/crypto++
|
||||
/usr/include/cryptopp
|
||||
/usr/local/include/crypto++
|
||||
/usr/local/include/cryptopp
|
||||
/opt/local/include/crypto++
|
||||
/opt/local/include/cryptopp
|
||||
find_path(CRYPTO++_INCLUDE_DIR cryptopp/cryptlib.h
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
$ENV{SystemDrive}/Crypto++/include
|
||||
$ENV{CRYPTOPP}
|
||||
$ENV{CRYPTOPP}/..
|
||||
$ENV{CRYPTOPP}/include
|
||||
${PROJECT_SOURCE_DIR}/../..
|
||||
)
|
||||
|
||||
find_library(CRYPTO++_LIBRARIES NAMES cryptopp
|
||||
@ -20,8 +20,34 @@ else(CRYPTO++_INCLUDE_DIR AND CRYPTO++_LIBRARIES)
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
$ENV{SystemDrive}/Crypto++/lib
|
||||
$ENV{CRYPTOPP}/lib
|
||||
)
|
||||
|
||||
if(MSVC AND NOT CRYPTO++_LIBRARIES) # Give a chance for MSVC multiconfig
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(PLATFORM x64)
|
||||
else()
|
||||
set(PLATFORM Win32)
|
||||
endif()
|
||||
find_library(CRYPTO++_LIBRARIES_RELEASE NAMES cryptlib cryptopp
|
||||
HINTS
|
||||
${PROJECT_SOURCE_DIR}/../../cryptopp/${PLATFORM}/Output/Release
|
||||
PATHS
|
||||
$ENV{CRYPTOPP}/Win32/Output/Release
|
||||
)
|
||||
find_library(CRYPTO++_LIBRARIES_DEBUG NAMES cryptlib cryptopp
|
||||
HINTS
|
||||
${PROJECT_SOURCE_DIR}/../../cryptopp/${PLATFORM}/Output/Debug
|
||||
PATHS
|
||||
$ENV{CRYPTOPP}/Win32/Output/Debug
|
||||
)
|
||||
set(CRYPTO++_LIBRARIES
|
||||
debug ${CRYPTO++_LIBRARIES_DEBUG}
|
||||
optimized ${CRYPTO++_LIBRARIES_RELEASE}
|
||||
CACHE PATH "Path to Crypto++ library" FORCE
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CRYPTO++_INCLUDE_DIR AND CRYPTO++_LIBRARIES)
|
||||
set(CRYPTO++_FOUND TRUE)
|
||||
message(STATUS "Found Crypto++: ${CRYPTO++_INCLUDE_DIR}, ${CRYPTO++_LIBRARIES}")
|
||||
|
25
build/cmake_modules/FindMiniUPnPc.cmake
Normal file
25
build/cmake_modules/FindMiniUPnPc.cmake
Normal file
@ -0,0 +1,25 @@
|
||||
# - Find MINIUPNPC
|
||||
|
||||
if(MINIUPNPC_INCLUDE_DIR)
|
||||
set(MINIUPNPC_FOUND TRUE)
|
||||
|
||||
else()
|
||||
find_path(MINIUPNPC_INCLUDE_DIR miniupnpc.h
|
||||
/usr/include/miniupnpc
|
||||
/usr/local/include/miniupnpc
|
||||
/opt/local/include/miniupnpc
|
||||
$ENV{SystemDrive}/miniupnpc
|
||||
${PROJECT_SOURCE_DIR}/../../miniupnpc
|
||||
)
|
||||
|
||||
if(MINIUPNPC_INCLUDE_DIR)
|
||||
set(MINIUPNPC_FOUND TRUE)
|
||||
message(STATUS "Found MiniUPnP headers: ${MINIUPNPC_INCLUDE_DIR}")
|
||||
else()
|
||||
set(MINIUPNPC_FOUND FALSE)
|
||||
message(STATUS "MiniUPnP not found.")
|
||||
endif()
|
||||
|
||||
mark_as_advanced(MINIUPNPC_INCLUDE_DIR)
|
||||
|
||||
endif()
|
1
stdafx.cpp
Normal file
1
stdafx.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "stdafx.h"
|
67
stdafx.h
Normal file
67
stdafx.h
Normal file
@ -0,0 +1,67 @@
|
||||
#ifndef STDAFX_H__
|
||||
#define STDAFX_H__
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <cassert>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <string.h> // TODO: replace with cstring and std::<old func> through out
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <utility>
|
||||
#include <cctype>
|
||||
#include <condition_variable>
|
||||
#include <chrono>
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/date_time/local_time/local_time.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/program_options/detail/config_file.hpp>
|
||||
#include <boost/program_options/parsers.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include <cryptopp/aes.h>
|
||||
#include <cryptopp/adler32.h>
|
||||
#include <cryptopp/asn.h>
|
||||
#include <cryptopp/base64.h>
|
||||
#include <cryptopp/crc.h>
|
||||
#include <cryptopp/dh.h>
|
||||
#include <cryptopp/dsa.h>
|
||||
#include <cryptopp/eccrypto.h>
|
||||
#include <cryptopp/gzip.h>
|
||||
#include <cryptopp/hmac.h>
|
||||
#include <cryptopp/integer.h>
|
||||
#include <cryptopp/modes.h>
|
||||
#include <cryptopp/osrng.h>
|
||||
#include <cryptopp/sha.h>
|
||||
#include <cryptopp/zinflate.h>
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user