mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-24 06:17:16 +01:00
commit
7c34c45983
|
@ -180,6 +180,18 @@ namespace http {
|
|||
case eRouterStatusOK: s << "OK"; break;
|
||||
case eRouterStatusTesting: s << "Testing"; break;
|
||||
case eRouterStatusFirewalled: s << "Firewalled"; break;
|
||||
case eRouterStatusError:
|
||||
{
|
||||
s << "Error";
|
||||
switch (i2p::context.GetError ())
|
||||
{
|
||||
case eRouterErrorClockSkew:
|
||||
s << "<br>Clock skew";
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: s << "Unknown";
|
||||
}
|
||||
s << "<br>\r\n";
|
||||
|
@ -344,50 +356,32 @@ namespace http {
|
|||
|
||||
void ShowLeasesSets(std::stringstream& s)
|
||||
{
|
||||
s << "<div id='leasesets'><b>LeaseSets:</b></div><br>";
|
||||
s << "<div id='leasesets'><b>LeaseSets (click on to show info):</b></div><br>\r\n";
|
||||
int counter = 1;
|
||||
// for each lease set
|
||||
i2p::data::netdb.VisitLeaseSets(
|
||||
[&s](const i2p::data::IdentHash dest, std::shared_ptr<i2p::data::LeaseSet> leaseSet)
|
||||
[&s, &counter](const i2p::data::IdentHash dest, std::shared_ptr<i2p::data::LeaseSet> leaseSet)
|
||||
{
|
||||
// create copy of lease set so we extract leases
|
||||
i2p::data::LeaseSet ls(leaseSet->GetBuffer(), leaseSet->GetBufferLen());
|
||||
// begin lease set entry
|
||||
s << "<div class='leaseset";
|
||||
if (ls.IsExpired())
|
||||
s << " expired"; // additional css class for expired
|
||||
s << "'>";
|
||||
// invalid ?
|
||||
s << "'>\r\n";
|
||||
if (!ls.IsValid())
|
||||
s << "<div class='invalid'>!! Invalid !! </div>";
|
||||
// ident
|
||||
s << "<div class='ident'>" << dest.ToBase32() << "</div>";
|
||||
// LeaseSet time
|
||||
s << "<div class='expires'>expires: " << ls.GetExpirationTime() << "</div>";
|
||||
// get non expired leases
|
||||
s << "<div class='invalid'>!! Invalid !! </div>\r\n";
|
||||
s << "<div class='slide'><label for='slide" << counter << "'>" << dest.ToBase32() << "</label>\r\n";
|
||||
s << "<input type='checkbox' id='slide" << (counter++) << "'/>\r\n<p class='content'>\r\n";
|
||||
s << "<b>Expires:</b> " << ls.GetExpirationTime() << "<br>\r\n";
|
||||
auto leases = ls.GetNonExpiredLeases();
|
||||
// show non expired leases
|
||||
s << "<div class='leasecount'>Non Expired Leases: " << leases.size() << "</div>";
|
||||
// for each lease
|
||||
s << "<div class='leases'>";
|
||||
s << "<b>Non Expired Leases: " << leases.size() << "</b><br>\r\n";
|
||||
for ( auto & l : leases )
|
||||
{
|
||||
// begin lease
|
||||
s << "<div class='lease'>";
|
||||
// gateway
|
||||
s << "<div class='gateway'>Gateway: " << l->tunnelGateway.ToBase64() << "</div>";
|
||||
// tunnel id
|
||||
s << "<div class='tunnelID'>TunnelID: " << l->tunnelID << "</div>";
|
||||
// end date
|
||||
s << "<div class='endDate'>EndDate: " << l->endDate << "</div>";
|
||||
// end lease
|
||||
s << "</div>";
|
||||
s << "<b>Gateway:</b> " << l->tunnelGateway.ToBase64() << "<br>\r\n";
|
||||
s << "<b>TunnelID:</b> " << l->tunnelID << "<br>\r\n";
|
||||
s << "<b>EndDate:</b> " << l->endDate << "<br>\r\n";
|
||||
}
|
||||
// end for each lease
|
||||
s << "</div>";
|
||||
// end lease set entry
|
||||
s << "</div>";
|
||||
// linebreak
|
||||
s << "<br>";
|
||||
s << "</p>\r\n</div>\r\n</div>\r\n";
|
||||
}
|
||||
);
|
||||
// end for each lease set
|
||||
|
|
2
I2CP.cpp
2
I2CP.cpp
|
@ -109,7 +109,7 @@ namespace client
|
|||
}
|
||||
else
|
||||
{
|
||||
auto outboundTunnel = GetTunnelPool ()->GetNextOutboundTunnel ();
|
||||
outboundTunnel = GetTunnelPool ()->GetNextOutboundTunnel ();
|
||||
auto leases = remote->GetNonExpiredLeases ();
|
||||
if (!leases.empty ())
|
||||
remoteLease = leases[rand () % leases.size ()];
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace i2p
|
|||
|
||||
RouterContext::RouterContext ():
|
||||
m_LastUpdateTime (0), m_AcceptsTunnels (true), m_IsFloodfill (false),
|
||||
m_StartupTime (0), m_Status (eRouterStatusOK )
|
||||
m_StartupTime (0), m_Status (eRouterStatusOK), m_Error (eRouterErrorNone)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -95,6 +95,7 @@ namespace i2p
|
|||
if (status != m_Status)
|
||||
{
|
||||
m_Status = status;
|
||||
m_Error = eRouterErrorNone;
|
||||
switch (m_Status)
|
||||
{
|
||||
case eRouterStatusOK:
|
||||
|
|
|
@ -20,9 +20,16 @@ namespace i2p
|
|||
{
|
||||
eRouterStatusOK = 0,
|
||||
eRouterStatusTesting = 1,
|
||||
eRouterStatusFirewalled = 2
|
||||
eRouterStatusFirewalled = 2,
|
||||
eRouterStatusError = 3
|
||||
};
|
||||
|
||||
enum RouterError
|
||||
{
|
||||
eRouterErrorNone = 0,
|
||||
eRouterErrorClockSkew = 1
|
||||
};
|
||||
|
||||
class RouterContext: public i2p::garlic::GarlicDestination
|
||||
{
|
||||
public:
|
||||
|
@ -49,7 +56,9 @@ namespace i2p
|
|||
uint64_t GetBandwidthLimit () const { return m_BandwidthLimit; };
|
||||
RouterStatus GetStatus () const { return m_Status; };
|
||||
void SetStatus (RouterStatus status);
|
||||
|
||||
RouterError GetError () const { return m_Error; };
|
||||
void SetError (RouterError error) { m_Status = eRouterStatusError; m_Error = error; };
|
||||
|
||||
void UpdatePort (int port); // called from Daemon
|
||||
void UpdateAddress (const boost::asio::ip::address& host); // called from SSU or Daemon
|
||||
bool AddIntroducer (const i2p::data::RouterInfo::Introducer& introducer);
|
||||
|
@ -107,6 +116,7 @@ namespace i2p
|
|||
uint64_t m_StartupTime; // in seconds since epoch
|
||||
uint32_t m_BandwidthLimit; // allowed bandwidth
|
||||
RouterStatus m_Status;
|
||||
RouterError m_Error;
|
||||
std::mutex m_GarlicMutex;
|
||||
};
|
||||
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
#include "I2PEndian.h"
|
||||
#include <fstream>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#if (BOOST_VERSION >= 105300)
|
||||
#include <boost/atomic.hpp>
|
||||
#endif
|
||||
#include "version.h"
|
||||
#include "Crypto.h"
|
||||
#include "Base.h"
|
||||
|
@ -17,14 +21,14 @@ namespace data
|
|||
{
|
||||
RouterInfo::RouterInfo (): m_Buffer (nullptr)
|
||||
{
|
||||
m_Addresses = std::make_shared<Addresses>(); // create empty list
|
||||
m_Addresses = boost::make_shared<Addresses>(); // create empty list
|
||||
}
|
||||
|
||||
RouterInfo::RouterInfo (const std::string& fullPath):
|
||||
m_FullPath (fullPath), m_IsUpdated (false), m_IsUnreachable (false),
|
||||
m_SupportedTransports (0), m_Caps (0)
|
||||
{
|
||||
m_Addresses = std::make_shared<Addresses>(); // create empty list
|
||||
m_Addresses = boost::make_shared<Addresses>(); // create empty list
|
||||
m_Buffer = new uint8_t[MAX_RI_BUFFER_SIZE];
|
||||
ReadFromFile ();
|
||||
}
|
||||
|
@ -32,7 +36,7 @@ namespace data
|
|||
RouterInfo::RouterInfo (const uint8_t * buf, int len):
|
||||
m_IsUpdated (true), m_IsUnreachable (false), m_SupportedTransports (0), m_Caps (0)
|
||||
{
|
||||
m_Addresses = std::make_shared<Addresses>(); // create empty list
|
||||
m_Addresses = boost::make_shared<Addresses>(); // create empty list
|
||||
m_Buffer = new uint8_t[MAX_RI_BUFFER_SIZE];
|
||||
memcpy (m_Buffer, buf, len);
|
||||
m_BufferLen = len;
|
||||
|
@ -154,7 +158,7 @@ namespace data
|
|||
s.read ((char *)&m_Timestamp, sizeof (m_Timestamp));
|
||||
m_Timestamp = be64toh (m_Timestamp);
|
||||
// read addresses
|
||||
auto addresses = std::make_shared<Addresses>();
|
||||
auto addresses = boost::make_shared<Addresses>();
|
||||
uint8_t numAddresses;
|
||||
s.read ((char *)&numAddresses, sizeof (numAddresses)); if (!s) return;
|
||||
bool introducers = false;
|
||||
|
@ -255,7 +259,11 @@ namespace data
|
|||
m_SupportedTransports |= supportedTransports;
|
||||
}
|
||||
}
|
||||
m_Addresses = addresses;
|
||||
#if (BOOST_VERSION >= 105300)
|
||||
boost::atomic_store (&m_Addresses, addresses);
|
||||
#else
|
||||
m_Addresses = addresses; // race condition
|
||||
#endif
|
||||
// read peers
|
||||
uint8_t numPeers;
|
||||
s.read ((char *)&numPeers, sizeof (numPeers)); if (!s) return;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <list>
|
||||
#include <iostream>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include "Identity.h"
|
||||
#include "Profiling.h"
|
||||
|
||||
|
@ -201,7 +202,7 @@ namespace data
|
|||
uint8_t * m_Buffer;
|
||||
size_t m_BufferLen;
|
||||
uint64_t m_Timestamp;
|
||||
std::shared_ptr<Addresses> m_Addresses;
|
||||
boost::shared_ptr<Addresses> m_Addresses; // TODO: use std::shared_ptr and std::atomic_store for gcc >= 4.9
|
||||
std::map<std::string, std::string> m_Properties;
|
||||
bool m_IsUpdated, m_IsUnreachable;
|
||||
uint8_t m_SupportedTransports, m_Caps;
|
||||
|
|
|
@ -272,6 +272,16 @@ namespace transport
|
|||
s.Insert (payload, 8); // relayTag and signed on time
|
||||
m_RelayTag = bufbe32toh (payload);
|
||||
payload += 4; // relayTag
|
||||
if (i2p::context.GetStatus () == eRouterStatusTesting)
|
||||
{
|
||||
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
||||
uint32_t signedOnTime = bufbe32toh(payload);
|
||||
if (signedOnTime < ts - SSU_CLOCK_SKEW || signedOnTime > ts + SSU_CLOCK_SKEW)
|
||||
{
|
||||
LogPrint (eLogError, "SSU: clock skew detected ", (int)ts - signedOnTime, ". Check your clock");
|
||||
i2p::context.SetError (eRouterErrorClockSkew);
|
||||
}
|
||||
}
|
||||
payload += 4; // signed on time
|
||||
// decrypt signature
|
||||
size_t signatureLen = m_RemoteIdentity->GetSignatureLen ();
|
||||
|
@ -310,6 +320,14 @@ namespace transport
|
|||
SetRemoteIdentity (std::make_shared<i2p::data::IdentityEx> (payload, identitySize));
|
||||
m_Data.UpdatePacketSize (m_RemoteIdentity->GetIdentHash ());
|
||||
payload += identitySize; // identity
|
||||
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
||||
uint32_t signedOnTime = bufbe32toh(payload);
|
||||
if (signedOnTime < ts - SSU_CLOCK_SKEW || signedOnTime > ts + SSU_CLOCK_SKEW)
|
||||
{
|
||||
LogPrint (eLogError, "SSU message 'confirmed' time difference ", (int)ts - signedOnTime, " exceeds clock skew");
|
||||
Failed ();
|
||||
return;
|
||||
}
|
||||
if (m_SignedData)
|
||||
m_SignedData->Insert (payload, 4); // insert Alice's signed on time
|
||||
payload += 4; // signed-on time
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace transport
|
|||
|
||||
const int SSU_CONNECT_TIMEOUT = 5; // 5 seconds
|
||||
const int SSU_TERMINATION_TIMEOUT = 330; // 5.5 minutes
|
||||
const int SSU_CLOCK_SKEW = 60; // in seconds
|
||||
|
||||
// payload types (4 bits)
|
||||
const uint8_t PAYLOAD_TYPE_SESSION_REQUEST = 0;
|
||||
|
|
50
Timestamp.cpp
Normal file
50
Timestamp.cpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <boost/asio.hpp>
|
||||
#include "I2PEndian.h"
|
||||
#include "Timestamp.h"
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
std::chrono::system_clock::duration g_TimeOffset = std::chrono::system_clock::duration::zero ();
|
||||
|
||||
void SyncTimeWithNTP (const std::string& address)
|
||||
{
|
||||
boost::asio::io_service service;
|
||||
boost::asio::ip::udp::resolver::query query (boost::asio::ip::udp::v4 (), address, "ntp");
|
||||
boost::system::error_code ec;
|
||||
auto it = boost::asio::ip::udp::resolver (service).resolve (query, ec);
|
||||
if (!ec && it != boost::asio::ip::udp::resolver::iterator())
|
||||
{
|
||||
auto ep = (*it).endpoint (); // take first one
|
||||
boost::asio::ip::udp::socket socket (service);
|
||||
socket.open (boost::asio::ip::udp::v4 (), ec);
|
||||
if (!ec)
|
||||
{
|
||||
uint8_t request[48];// 48 bytes NTP request
|
||||
memset (request, 0, 48);
|
||||
request[0] = 0x80; // client mode, version 0
|
||||
uint8_t * response = new uint8_t[1500]; // MTU
|
||||
size_t len = 0;
|
||||
try
|
||||
{
|
||||
socket.send_to (boost::asio::buffer (request, 48), ep);
|
||||
len = socket.receive_from (boost::asio::buffer (response, 1500), ep);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
}
|
||||
if (len >= 8)
|
||||
{
|
||||
uint32_t ts = bufbe32toh (response + 4);
|
||||
if (ts > 2208988800U) ts -= 2208988800U; // 1/1/1970 from 1/1/1900
|
||||
}
|
||||
delete[] response;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,8 @@ namespace i2p
|
|||
{
|
||||
namespace util
|
||||
{
|
||||
extern std::chrono::system_clock::duration g_TimeOffset;
|
||||
|
||||
inline uint64_t GetMillisecondsSinceEpoch ()
|
||||
{
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
|
|
|
@ -57,6 +57,7 @@ LOCAL_SRC_FILES := DaemonAndroid.cpp i2pd_android.cpp \
|
|||
../../TunnelEndpoint.cpp \
|
||||
../../TunnelGateway.cpp \
|
||||
../../TunnelPool.cpp \
|
||||
../../Timestamp.cpp \
|
||||
../../util.cpp \
|
||||
../../i2pd.cpp ../../UPnP.cpp
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ set (LIBI2PD_SRC
|
|||
"${CMAKE_SOURCE_DIR}/Datagram.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/Family.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/Signature.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/Timestamp.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/api.cpp"
|
||||
)
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ msys2
|
|||
|
||||
### x86 (32-bit architecture)
|
||||
|
||||
Get install file msys2-i686-20150916.exe from https://msys2.github.io.
|
||||
Get install file msys2-i686-*.exe from https://msys2.github.io.
|
||||
open MSYS2 Shell (from Start menu).
|
||||
Install all prerequisites and download i2pd source:
|
||||
|
||||
|
@ -44,7 +44,7 @@ make
|
|||
|
||||
### x64 (64-bit architecture)
|
||||
|
||||
Get install file msys2-x86_64-20150916.exe from https://msys2.github.io.
|
||||
Get install file msys2-x86_64-*.exe from https://msys2.github.io.
|
||||
open MSYS2 Shell (from Start menu).
|
||||
Install all prerequisites and download i2pd source:
|
||||
|
||||
|
@ -97,9 +97,9 @@ Requirements for building:
|
|||
* [CMake](https://cmake.org/) (tested with 3.1.3)
|
||||
* [Visual Studio Community Edition](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx) (tested with VS2013 Update 4)
|
||||
* [Boost](http://www.boost.org/) (tested with 1.59)
|
||||
* Optionally [MiniUPnP](http://miniupnp.free.f) (tested with 1.9), we need only few client headers
|
||||
* Optionally [MiniUPnP](http://miniupnp.free.fr) (tested with 1.9), we need only few client headers
|
||||
* OpenSSL (tested with 1.0.1p and 1.0.2e), if building from sources (recommended), you'll need as well
|
||||
* [Netwide assembler](www.nasm.us)
|
||||
* [Netwide assembler](http://www.nasm.us/)
|
||||
* Strawberry Perl or ActiveState Perl, do NOT try msys2 perl, it won't work
|
||||
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ LIB_SRC = \
|
|||
SSUSession.cpp SSUData.cpp Streaming.cpp Identity.cpp TransitTunnel.cpp \
|
||||
Transports.cpp Tunnel.cpp TunnelEndpoint.cpp TunnelPool.cpp TunnelGateway.cpp \
|
||||
Destination.cpp Base.cpp I2PEndian.cpp FS.cpp Config.cpp Family.cpp \
|
||||
Config.cpp HTTP.cpp util.cpp api.cpp
|
||||
Config.cpp HTTP.cpp Timestamp.cpp util.cpp api.cpp
|
||||
|
||||
LIB_CLIENT_SRC = \
|
||||
AddressBook.cpp BOB.cpp ClientContext.cpp I2PTunnel.cpp I2PService.cpp \
|
||||
|
|
|
@ -35,7 +35,8 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \
|
|||
../../RouterInfo.cpp ../../SAM.cpp ../../Signature.cpp ../../SOCKS.cpp ../../SSU.cpp \
|
||||
../../SSUData.cpp ../../SSUSession.cpp ../../Streaming.cpp ../../TransitTunnel.cpp \
|
||||
../../Transports.cpp ../../Tunnel.cpp ../../TunnelEndpoint.cpp ../../TunnelGateway.cpp \
|
||||
../../TunnelPool.cpp ../../UPnP.cpp ../../util.cpp ../../Gzip.cpp ../../i2pd.cpp
|
||||
../../TunnelPool.cpp ../../UPnP.cpp ../../Gzip.cpp ../../Timestamp.cpp ../../util.cpp \
|
||||
../../i2pd.cpp
|
||||
|
||||
HEADERS += DaemonQT.h mainwindow.h \
|
||||
../../HTTPServer.h ../../I2PControl.h ../../UPnP.h ../../Daemon.h ../../Config.h \
|
||||
|
|
Loading…
Reference in a new issue