Merge pull request #373 from PurpleI2P/openssl

recent changes
pull/391/head
orignal 9 years ago
commit c9d5b3c0ff

@ -113,6 +113,7 @@ namespace config {
("log", value<std::string>()->default_value(""), "Logs destination: stdout, file (stdout if not set, file - otherwise, for compatibility)")
("logfile", value<std::string>()->default_value(""), "Path to logfile (stdout if not set, autodetect if daemon)")
("loglevel", value<std::string>()->default_value("info"), "Set the minimal level of log messages (debug, info, warn, error)")
("datadir", value<std::string>()->default_value(""), "Path to storage of i2pd data (RI, keys, peer profiles, ...)")
("host", value<std::string>()->default_value("0.0.0.0"), "External IP")
("port", value<uint16_t>()->default_value(0), "Port to listen for incoming connections (default: auto)")
("ipv6", value<bool>()->zero_tokens()->default_value(false), "Enable communication through ipv6")
@ -223,6 +224,15 @@ namespace config {
void Finalize() {
notify(m_Options);
};
}
bool IsDefault(const char *name) {
if (!m_Options.count(name))
throw "try to check non-existent option";
if (m_Options[name].defaulted())
return true;
return false;
}
} // namespace config
} // namespace i2p

@ -94,6 +94,13 @@ namespace config {
notify(m_Options);
return true;
}
/**
* @brief Check is value explicitly given or default
* @param name Name of checked parameter
* @return true if value set to default, false othervise
*/
bool IsDefault(const char *name);
}
}

@ -83,14 +83,14 @@ namespace i2p
LogPrint(eLogDebug, "FS: data directory: ", datadir);
uint16_t port; i2p::config::GetOption("port", port);
if (port)
if (!i2p::config::IsDefault("port"))
{
LogPrint(eLogInfo, "Daemon: accepting incoming connections at port ", port);
i2p::context.UpdatePort (port);
}
std::string host; i2p::config::GetOption("host", host);
if (host != "0.0.0.0")
if (!i2p::config::IsDefault("host"))
{
LogPrint(eLogInfo, "Daemon: setting address for incoming connections to ", host);
i2p::context.UpdateAddress (boost::asio::ip::address::from_string (host));
@ -125,7 +125,10 @@ namespace i2p
i2p::context.SetExtraBandwidth ();
}
else
{
LogPrint(eLogInfo, "Daemon: bandwidth set to 'low'");
i2p::context.SetLowBandwidth ();
}
return true;
}

@ -66,7 +66,7 @@ namespace datagram
msgs.push_back (i2p::tunnel::TunnelMessageBlock
{
i2p::tunnel::eDeliveryTypeTunnel,
leases[i].tunnelGateway, leases[i].tunnelID,
leases[i]->tunnelGateway, leases[i]->tunnelID,
garlic
});
outboundTunnel->SendTunnelDataMsg (msgs);

@ -303,7 +303,7 @@ namespace client
}
else
{
LogPrint (eLogError, "New remote LeaseSet verification failed");
LogPrint (eLogError, "New remote LeaseSet failed");
leaseSet = nullptr;
}
}
@ -678,7 +678,7 @@ namespace client
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
for (auto it = m_RemoteLeaseSets.begin (); it != m_RemoteLeaseSets.end ();)
{
if (ts > it->second->GetExpirationTime ()) // leaseset expired
if (it->second->IsEmpty () || ts > it->second->GetExpirationTime ()) // leaseset expired
{
LogPrint (eLogWarning, "Destination: Remote LeaseSet ", it->second->GetIdentHash ().ToBase64 (), " expired");
it = m_RemoteLeaseSets.erase (it);

@ -265,9 +265,9 @@ namespace i2p
auto leases = leaseSet->GetNonExpiredLeases ();
if (leases.size () > 0)
{
htobe32buf (payload + size, leases[0].tunnelID);
htobe32buf (payload + size, leases[0]->tunnelID);
size += 4; // reply tunnelID
memcpy (payload + size, leases[0].tunnelGateway, 32);
memcpy (payload + size, leases[0]->tunnelGateway, 32);
size += 32; // reply tunnel gateway
}
else

@ -69,7 +69,6 @@ namespace data
void LeaseSet::Update (const uint8_t * buf, size_t len)
{
m_Leases.clear ();
if (len > m_BufferLen)
{
auto oldBuffer = m_Buffer;
@ -84,7 +83,6 @@ namespace data
void LeaseSet::PopulateLeases ()
{
m_StoreLeases = true;
m_Leases.clear ();
ReadFromBuffer (false);
}
@ -112,8 +110,16 @@ namespace data
return;
}
// reset existing leases
if (m_StoreLeases)
for (auto it: m_Leases)
it->isUpdated = false;
else
m_Leases.clear ();
// process leases
m_ExpirationTime = 0;
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
const uint8_t * leases = m_Buffer + size;
for (int i = 0; i < num; i++)
{
@ -124,21 +130,48 @@ namespace data
leases += 4; // tunnel ID
lease.endDate = bufbe64toh (leases);
leases += 8; // end date
if (lease.endDate > m_ExpirationTime)
m_ExpirationTime = lease.endDate;
if (m_StoreLeases)
if (ts < lease.endDate)
{
m_Leases.push_back (lease);
// check if lease's gateway is in our netDb
if (!netdb.FindRouter (lease.tunnelGateway))
{
// if not found request it
LogPrint (eLogInfo, "LeaseSet: Lease's tunnel gateway not found, requesting");
netdb.RequestDestination (lease.tunnelGateway);
}
}
if (lease.endDate > m_ExpirationTime)
m_ExpirationTime = lease.endDate;
if (m_StoreLeases)
{
auto ret = m_Leases.insert (std::make_shared<Lease>(lease));
if (!ret.second) *(*ret.first) = lease; // update existing
(*ret.first)->isUpdated = true;
// check if lease's gateway is in our netDb
if (!netdb.FindRouter (lease.tunnelGateway))
{
// if not found request it
LogPrint (eLogInfo, "LeaseSet: Lease's tunnel gateway not found, requesting");
netdb.RequestDestination (lease.tunnelGateway);
}
}
}
else
LogPrint (eLogWarning, "LeaseSet: Lease is expired already ");
}
if (!m_ExpirationTime)
{
LogPrint (eLogWarning, "LeaseSet: all leases are expired. Dropped");
m_IsValid = false;
return;
}
// delete old leases
if (m_StoreLeases)
{
for (auto it = m_Leases.begin (); it != m_Leases.end ();)
{
if (!(*it)->isUpdated)
{
(*it)->endDate = 0; // somebody might still hold it
m_Leases.erase (it++);
}
else
it++;
}
}
// verify
if (!m_Identity->Verify (m_Buffer, leases - m_Buffer, leases))
{
@ -147,13 +180,13 @@ namespace data
}
}
const std::vector<Lease> LeaseSet::GetNonExpiredLeases (bool withThreshold) const
const std::vector<std::shared_ptr<Lease> > LeaseSet::GetNonExpiredLeases (bool withThreshold) const
{
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
std::vector<Lease> leases;
for (auto& it: m_Leases)
std::vector<std::shared_ptr<Lease> > leases;
for (auto it: m_Leases)
{
auto endDate = it.endDate;
auto endDate = it->endDate;
if (!withThreshold)
endDate -= i2p::tunnel::TUNNEL_EXPIRATION_THRESHOLD*1000;
if (ts < endDate)
@ -165,13 +198,14 @@ namespace data
bool LeaseSet::HasExpiredLeases () const
{
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
for (auto& it: m_Leases)
if (ts >= it.endDate) return true;
for (auto it: m_Leases)
if (ts >= it->endDate) return true;
return false;
}
bool LeaseSet::IsExpired () const
{
if (IsEmpty ()) return true;
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
return ts > m_ExpirationTime;
}

@ -4,6 +4,7 @@
#include <inttypes.h>
#include <string.h>
#include <vector>
#include <memory>
#include "Identity.h"
namespace i2p
@ -20,15 +21,19 @@ namespace data
{
IdentHash tunnelGateway;
uint32_t tunnelID;
uint64_t endDate;
uint64_t endDate; // 0 means invalid
bool isUpdated; // trasient
};
bool operator< (const Lease& other) const
{
if (endDate != other.endDate)
return endDate > other.endDate;
struct LeaseCmp
{
bool operator() (std::shared_ptr<const Lease> l1, std::shared_ptr<const Lease> l2) const
{
if (l1->tunnelID != l2->tunnelID)
return l1->tunnelID < l2->tunnelID;
else
return tunnelID < other.tunnelID;
}
return l1->tunnelGateway < l2->tunnelGateway;
};
};
const int MAX_LS_BUFFER_SIZE = 3072;
@ -41,20 +46,20 @@ namespace data
LeaseSet (std::shared_ptr<const i2p::tunnel::TunnelPool> pool);
~LeaseSet () { delete[] m_Buffer; };
void Update (const uint8_t * buf, size_t len);
void PopulateLeases (); /// from buffer
void PopulateLeases (); // from buffer
std::shared_ptr<const IdentityEx> GetIdentity () const { return m_Identity; };
const uint8_t * GetBuffer () const { return m_Buffer; };
size_t GetBufferLen () const { return m_BufferLen; };
bool IsValid () const { return m_IsValid; };
// implements RoutingDestination
const IdentHash& GetIdentHash () const { return m_Identity->GetIdentHash (); };
const std::vector<Lease>& GetLeases () const { return m_Leases; };
const std::vector<Lease> GetNonExpiredLeases (bool withThreshold = true) const;
const std::vector<std::shared_ptr<Lease> > GetNonExpiredLeases (bool withThreshold = true) const;
bool HasExpiredLeases () const;
bool IsExpired () const;
bool IsEmpty () const { return m_Leases.empty (); };
uint64_t GetExpirationTime () const { return m_ExpirationTime; };
// implements RoutingDestination
const IdentHash& GetIdentHash () const { return m_Identity->GetIdentHash (); };
const uint8_t * GetEncryptionPublicKey () const { return m_EncryptionKey; };
bool IsDestination () const { return true; };
@ -65,7 +70,7 @@ namespace data
private:
bool m_IsValid, m_StoreLeases; // we don't need to store leases for floodfill
std::vector<Lease> m_Leases;
std::set<std::shared_ptr<Lease>, LeaseCmp> m_Leases;
uint64_t m_ExpirationTime; // in milliseconds
std::shared_ptr<const IdentityEx> m_Identity;
uint8_t m_EncryptionKey[256];

@ -736,7 +736,7 @@ namespace transport
{
if (ecode != boost::asio::error::operation_aborted)
{
LogPrint (eLogWarning, "NTCP: No activity fo ", NTCP_TERMINATION_TIMEOUT, " seconds");
LogPrint (eLogWarning, "NTCP: No activity for ", NTCP_TERMINATION_TIMEOUT, " seconds");
//Terminate ();
m_Socket.close ();// invoke Terminate () from HandleReceive
}

@ -48,7 +48,7 @@ namespace i2p
if (!port)
port = rand () % (30777 - 9111) + 9111; // I2P network ports range
std::string host; i2p::config::GetOption("host", host);
if (host == "0.0.0.0")
if (i2p::config::IsDefault("host"))
host = "127.0.0.1"; // replace default address with safe value
routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ());
routerInfo.AddNTCPAddress (host.c_str(), port);

@ -22,7 +22,6 @@ namespace stream
{
RAND_bytes ((uint8_t *)&m_RecvStreamID, 4);
m_RemoteIdentity = remote->GetIdentity ();
m_CurrentRemoteLease.endDate = 0;
}
Stream::Stream (boost::asio::io_service& service, StreamingDestination& local):
@ -599,9 +598,9 @@ namespace stream
}
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
if (!m_CurrentRemoteLease.endDate || ts >= m_CurrentRemoteLease.endDate - i2p::tunnel::TUNNEL_EXPIRATION_THRESHOLD*1000)
if (!m_CurrentRemoteLease || ts >= m_CurrentRemoteLease->endDate - i2p::tunnel::TUNNEL_EXPIRATION_THRESHOLD*1000)
UpdateCurrentRemoteLease (true);
if (ts < m_CurrentRemoteLease.endDate)
if (m_CurrentRemoteLease && ts < m_CurrentRemoteLease->endDate)
{
std::vector<i2p::tunnel::TunnelMessageBlock> msgs;
for (auto it: packets)
@ -610,7 +609,7 @@ namespace stream
msgs.push_back (i2p::tunnel::TunnelMessageBlock
{
i2p::tunnel::eDeliveryTypeTunnel,
m_CurrentRemoteLease.tunnelGateway, m_CurrentRemoteLease.tunnelID,
m_CurrentRemoteLease->tunnelGateway, m_CurrentRemoteLease->tunnelID,
msg
});
m_NumSentBytes += it->GetLength ();
@ -705,11 +704,11 @@ namespace stream
void Stream::UpdateCurrentRemoteLease (bool expired)
{
if (!m_RemoteLeaseSet)
if (!m_RemoteLeaseSet || m_RemoteLeaseSet->IsExpired ())
{
m_RemoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ());
if (!m_RemoteLeaseSet)
LogPrint (eLogError, "Streaming: LeaseSet ", m_RemoteIdentity->GetIdentHash ().ToBase64 (), " not found");
if (!m_RemoteLeaseSet)
LogPrint (eLogWarning, "Streaming: LeaseSet ", m_RemoteIdentity->GetIdentHash ().ToBase64 (), " not found");
}
if (m_RemoteLeaseSet)
{
@ -725,10 +724,10 @@ namespace stream
if (!leases.empty ())
{
bool updated = false;
if (expired)
if (expired && m_CurrentRemoteLease)
{
for (auto it: leases)
if ((it.tunnelGateway == m_CurrentRemoteLease.tunnelGateway) && (it.tunnelID != m_CurrentRemoteLease.tunnelID))
if ((it->tunnelGateway == m_CurrentRemoteLease->tunnelGateway) && (it->tunnelID != m_CurrentRemoteLease->tunnelID))
{
m_CurrentRemoteLease = it;
updated = true;
@ -738,7 +737,7 @@ namespace stream
if (!updated)
{
uint32_t i = rand () % leases.size ();
if (m_CurrentRemoteLease.endDate && leases[i].tunnelID == m_CurrentRemoteLease.tunnelID)
if (m_CurrentRemoteLease && leases[i]->tunnelID == m_CurrentRemoteLease->tunnelID)
// make sure we don't select previous
i = (i + 1) % leases.size (); // if so, pick next
m_CurrentRemoteLease = leases[i];
@ -747,12 +746,12 @@ namespace stream
else
{
m_RemoteLeaseSet = nullptr;
m_CurrentRemoteLease.endDate = 0;
m_CurrentRemoteLease = nullptr;
// re-request expired
}
}
else
m_CurrentRemoteLease.endDate = 0;
m_CurrentRemoteLease = nullptr;
}
std::shared_ptr<I2NPMessage> Stream::CreateDataMessage (const uint8_t * payload, size_t len)
@ -879,7 +878,7 @@ namespace stream
it->second.push_back (packet);
else
{
m_SavedPackets.emplace (receiveStreamID, std::list<Packet *>{ packet });
m_SavedPackets[receiveStreamID] = std::list<Packet *>{ packet };
auto timer = std::make_shared<boost::asio::deadline_timer> (m_Owner->GetService ());
timer->expires_from_now (boost::posix_time::seconds(PENDING_INCOMING_TIMEOUT));
auto s = shared_from_this ();

@ -172,7 +172,7 @@ namespace stream
std::shared_ptr<const i2p::data::IdentityEx> m_RemoteIdentity;
std::shared_ptr<const i2p::data::LeaseSet> m_RemoteLeaseSet;
std::shared_ptr<i2p::garlic::GarlicRoutingSession> m_RoutingSession;
i2p::data::Lease m_CurrentRemoteLease;
std::shared_ptr<i2p::data::Lease> m_CurrentRemoteLease;
std::shared_ptr<i2p::tunnel::OutboundTunnel> m_CurrentOutboundTunnel;
std::queue<Packet *> m_ReceiveQueue;
std::set<Packet *, PacketCmp> m_SavedPackets;

@ -666,6 +666,10 @@ namespace tunnel
{
// trying to create one more inbound tunnel
auto router = i2p::data::netdb.GetRandomRouter ();
if (!router) {
LogPrint (eLogWarning, "Tunnel: can't find any router, skip creating tunnel");
return;
}
LogPrint (eLogDebug, "Tunnel: creating one hop inbound tunnel");
CreateTunnel<InboundTunnel> (
std::make_shared<TunnelConfig> (std::vector<std::shared_ptr<const i2p::data::IdentityEx> > { router->GetRouterIdentity () })

6
debian/i2pd.init vendored

@ -18,6 +18,7 @@ DAEMON_OPTS="" # Arguments to run the daemon with
PIDFILE=/var/run/$NAME.pid
I2PCONF=/etc/$NAME/i2pd.conf
TUNCONF=/etc/$NAME/tunnels.conf
LOGFILE=/var/log/$NAME.log
USER="i2pd"
# Exit if the package is not installed
@ -43,10 +44,13 @@ do_start()
touch "$PIDFILE"
chown -f $USER:adm "$PIDFILE"
touch "$LOGFILE"
chown -f $USER:adm "$LOGFILE"
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --chuid "$USER" --test > /dev/null \
|| return 1
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --chuid "$USER" -- \
--service --daemon --log --conf=$I2PCONF --tunconf=$TUNCONF \
--service --daemon --log=file --logfile=$LOGFILE --conf=$I2PCONF --tunconf=$TUNCONF \
--port=$I2PD_PORT $DAEMON_OPTS > /dev/null 2>&1 \
|| return 2
return $?

@ -6,5 +6,6 @@ stop on runlevel [016] or unmounting-filesystem
# these can be overridden in /etc/init/i2pd.override
env I2PD_HOST="1.2.3.4"
env I2PD_PORT="4567"
env LOGFILE="/var/log/i2pd.log"
exec /usr/sbin/i2pd --daemon --log --host=$I2PD_HOST --port=$I2PD_PORT
exec /usr/sbin/i2pd --daemon --log=file --logfile=$LOGFILE --service --host=$I2PD_HOST --port=$I2PD_PORT

@ -12,6 +12,7 @@ Command line options
* --log= - Logs destination: stdout, file (stdout if not set, file - otherwise, for compatibility)
* --logfile= - Path to logfile (default - autodetect)
* --loglevel= - Log messages above this level (debug, *info, warn, error)
* --datadir= - Path to storage of i2pd data (RI, keys, peer profiles, ...)
* --host= - The external IP
* --port= - The port to listen on
* --daemon - Router will go to background after start

Loading…
Cancel
Save