Time experemental options

This commit is contained in:
Alex 2018-03-01 08:58:05 +07:00
parent 5a2b795440
commit ea899fbbfd
17 changed files with 264 additions and 129 deletions

View file

@ -64,6 +64,8 @@ namespace i2p
{ {
i2p::config::Init(); i2p::config::Init();
i2p::config::ParseCmdline(argc, argv); i2p::config::ParseCmdline(argc, argv);
std::string config; i2p::config::GetOption("conf", config); std::string config; i2p::config::GetOption("conf", config);
std::string datadir; i2p::config::GetOption("datadir", datadir); std::string datadir; i2p::config::GetOption("datadir", datadir);
@ -247,12 +249,17 @@ namespace i2p
LogPrint(eLogInfo, "Daemon: using hidden mode"); LogPrint(eLogInfo, "Daemon: using hidden mode");
i2p::data::netdb.SetHidden(true); i2p::data::netdb.SetHidden(true);
} }
return true; return true;
} }
bool Daemon_Singleton::start() bool Daemon_Singleton::start()
{ {
i2p::log::Logger().Start(); i2p::log::Logger().Start();
i2p::util::SyncTimeWithNTP();
LogPrint(eLogInfo, "Daemon: starting NetDB"); LogPrint(eLogInfo, "Daemon: starting NetDB");
i2p::data::netdb.Start(); i2p::data::netdb.Start();
@ -264,7 +271,12 @@ namespace i2p
bool ntcp; i2p::config::GetOption("ntcp", ntcp); bool ntcp; i2p::config::GetOption("ntcp", ntcp);
bool ssu; i2p::config::GetOption("ssu", ssu); bool ssu; i2p::config::GetOption("ssu", ssu);
LogPrint(eLogInfo, "Daemon: starting Transports");
LogPrint(eLogInfo, "Daemon: starting Transports");
if(!ssu) LogPrint(eLogInfo, "Daemon: ssu disabled"); if(!ssu) LogPrint(eLogInfo, "Daemon: ssu disabled");
if(!ntcp) LogPrint(eLogInfo, "Daemon: ntcp disabled"); if(!ntcp) LogPrint(eLogInfo, "Daemon: ntcp disabled");

View file

@ -15,7 +15,7 @@ namespace util
virtual bool init(int argc, char* argv[]); virtual bool init(int argc, char* argv[]);
virtual bool start(); virtual bool start();
virtual bool stop(); virtual bool stop();
virtual void run () {}; virtual void run () { };
bool isDaemon; bool isDaemon;
bool running; bool running;

View file

@ -230,6 +230,12 @@ namespace config {
("exploratory.inbound.quantity", value<int>()->default_value(3), "Exploratory inbound tunnels quantity") ("exploratory.inbound.quantity", value<int>()->default_value(3), "Exploratory inbound tunnels quantity")
("exploratory.outbound.quantity", value<int>()->default_value(3), "Exploratory outbound tunnels quantity") ("exploratory.outbound.quantity", value<int>()->default_value(3), "Exploratory outbound tunnels quantity")
; ;
options_description time("Time Options");
time.add_options()
("time.use_ntp", value<bool>()->default_value(false), "Use NTP")
("time.correcting", value<bool>()->default_value(false), "EXPEREMENTAL: Try correcting with peer, unsecurity")
("time.ntp_server", value<std::string>()->default_value(offical_ntp_server), "NTP Server host")
;
m_OptionsDesc m_OptionsDesc
.add(general) .add(general)
@ -248,6 +254,7 @@ namespace config {
.add(trust) .add(trust)
.add(websocket) .add(websocket)
.add(exploratory) .add(exploratory)
.add(time)
; ;
} }

View file

@ -18,6 +18,12 @@
namespace i2p { namespace i2p {
namespace config { namespace config {
constexpr const char offical_ntp_server[] = "0.pool.ntp.org,"
"1.pool.ntp.org,"
"2.pool.ntp.org,"
"3.pool.ntp.org";
extern boost::program_options::variables_map m_Options; extern boost::program_options::variables_map m_Options;
/** /**

View file

@ -483,7 +483,7 @@ namespace client
LogPrint (eLogDebug, "Destination: Publishing LeaseSet is pending"); LogPrint (eLogDebug, "Destination: Publishing LeaseSet is pending");
return; return;
} }
auto ts = i2p::util::GetSecondsSinceEpoch (); auto ts = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds);
if (ts < m_LastSubmissionTime + PUBLISH_MIN_INTERVAL) if (ts < m_LastSubmissionTime + PUBLISH_MIN_INTERVAL)
{ {
LogPrint (eLogDebug, "Destination: Publishing LeaseSet is too fast. Wait for ", PUBLISH_MIN_INTERVAL, " seconds"); LogPrint (eLogDebug, "Destination: Publishing LeaseSet is too fast. Wait for ", PUBLISH_MIN_INTERVAL, " seconds");
@ -621,7 +621,7 @@ namespace client
auto request = std::make_shared<LeaseSetRequest> (m_Service); auto request = std::make_shared<LeaseSetRequest> (m_Service);
if (requestComplete) if (requestComplete)
request->requestComplete.push_back (requestComplete); request->requestComplete.push_back (requestComplete);
auto ts = i2p::util::GetSecondsSinceEpoch (); auto ts = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds);
auto ret = m_LeaseSetRequests.insert (std::pair<i2p::data::IdentHash, std::shared_ptr<LeaseSetRequest> >(dest,request)); auto ret = m_LeaseSetRequests.insert (std::pair<i2p::data::IdentHash, std::shared_ptr<LeaseSetRequest> >(dest,request));
if (ret.second) // inserted if (ret.second) // inserted
{ {
@ -701,7 +701,7 @@ namespace client
if (it != m_LeaseSetRequests.end ()) if (it != m_LeaseSetRequests.end ())
{ {
bool done = false; bool done = false;
uint64_t ts = i2p::util::GetSecondsSinceEpoch (); int64_t ts = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds);
if (ts < it->second->requestTime + MAX_LEASESET_REQUEST_TIMEOUT) if (ts < it->second->requestTime + MAX_LEASESET_REQUEST_TIMEOUT)
{ {
auto floodfill = i2p::data::netdb.GetClosestFloodfill (dest, it->second->excluded); auto floodfill = i2p::data::netdb.GetClosestFloodfill (dest, it->second->excluded);

View file

@ -34,7 +34,7 @@ namespace garlic
memcpy (m_SessionKey, sessionKey, 32); memcpy (m_SessionKey, sessionKey, 32);
m_Encryption.SetKey (m_SessionKey); m_Encryption.SetKey (m_SessionKey);
m_SessionTags.push_back (sessionTag); m_SessionTags.push_back (sessionTag);
m_SessionTags.back ().creationTime = i2p::util::GetSecondsSinceEpoch (); m_SessionTags.back ().creationTime = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ;
} }
GarlicRoutingSession::~GarlicRoutingSession () GarlicRoutingSession::~GarlicRoutingSession ()
@ -44,7 +44,7 @@ namespace garlic
std::shared_ptr<GarlicRoutingPath> GarlicRoutingSession::GetSharedRoutingPath () std::shared_ptr<GarlicRoutingPath> GarlicRoutingSession::GetSharedRoutingPath ()
{ {
if (!m_SharedRoutingPath) return nullptr; if (!m_SharedRoutingPath) return nullptr;
uint32_t ts = i2p::util::GetSecondsSinceEpoch (); uint32_t ts = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ;
if (m_SharedRoutingPath->numTimesUsed >= ROUTING_PATH_MAX_NUM_TIMES_USED || if (m_SharedRoutingPath->numTimesUsed >= ROUTING_PATH_MAX_NUM_TIMES_USED ||
!m_SharedRoutingPath->outboundTunnel->IsEstablished () || !m_SharedRoutingPath->outboundTunnel->IsEstablished () ||
ts*1000LL > m_SharedRoutingPath->remoteLease->endDate || ts*1000LL > m_SharedRoutingPath->remoteLease->endDate ||
@ -58,7 +58,7 @@ namespace garlic
{ {
if (path && path->outboundTunnel && path->remoteLease) if (path && path->outboundTunnel && path->remoteLease)
{ {
path->updateTime = i2p::util::GetSecondsSinceEpoch (); path->updateTime = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ;
path->numTimesUsed = 0; path->numTimesUsed = 0;
} }
else else
@ -69,7 +69,7 @@ namespace garlic
GarlicRoutingSession::UnconfirmedTags * GarlicRoutingSession::GenerateSessionTags () GarlicRoutingSession::UnconfirmedTags * GarlicRoutingSession::GenerateSessionTags ()
{ {
auto tags = new UnconfirmedTags (m_NumTags); auto tags = new UnconfirmedTags (m_NumTags);
tags->tagsCreationTime = i2p::util::GetSecondsSinceEpoch (); tags->tagsCreationTime = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ;
for (int i = 0; i < m_NumTags; i++) for (int i = 0; i < m_NumTags; i++)
{ {
RAND_bytes (tags->sessionTags[i], 32); RAND_bytes (tags->sessionTags[i], 32);
@ -93,7 +93,7 @@ namespace garlic
void GarlicRoutingSession::TagsConfirmed (uint32_t msgID) void GarlicRoutingSession::TagsConfirmed (uint32_t msgID)
{ {
uint32_t ts = i2p::util::GetSecondsSinceEpoch (); uint32_t ts = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ;
auto it = m_UnconfirmedTagsMsgs.find (msgID); auto it = m_UnconfirmedTagsMsgs.find (msgID);
if (it != m_UnconfirmedTagsMsgs.end ()) if (it != m_UnconfirmedTagsMsgs.end ())
{ {
@ -109,7 +109,7 @@ namespace garlic
bool GarlicRoutingSession::CleanupExpiredTags () bool GarlicRoutingSession::CleanupExpiredTags ()
{ {
auto ts = i2p::util::GetSecondsSinceEpoch (); auto ts = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ;
for (auto it = m_SessionTags.begin (); it != m_SessionTags.end ();) for (auto it = m_SessionTags.begin (); it != m_SessionTags.end ();)
{ {
if (ts >= it->creationTime + OUTGOING_TAGS_EXPIRATION_TIMEOUT) if (ts >= it->creationTime + OUTGOING_TAGS_EXPIRATION_TIMEOUT)
@ -130,7 +130,7 @@ namespace garlic
bool GarlicRoutingSession::CleanupUnconfirmedTags () bool GarlicRoutingSession::CleanupUnconfirmedTags ()
{ {
bool ret = false; bool ret = false;
uint32_t ts = i2p::util::GetSecondsSinceEpoch (); uint32_t ts = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ;
// delete expired unconfirmed tags // delete expired unconfirmed tags
for (auto it = m_UnconfirmedTagsMsgs.begin (); it != m_UnconfirmedTagsMsgs.end ();) for (auto it = m_UnconfirmedTagsMsgs.begin (); it != m_UnconfirmedTagsMsgs.end ();)
{ {
@ -159,7 +159,7 @@ namespace garlic
SessionTag tag; SessionTag tag;
if (m_NumTags > 0) if (m_NumTags > 0)
{ {
uint32_t ts = i2p::util::GetSecondsSinceEpoch (); uint32_t ts = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ;
while (!m_SessionTags.empty ()) while (!m_SessionTags.empty ())
{ {
if (ts < m_SessionTags.front ().creationTime + OUTGOING_TAGS_EXPIRATION_TIMEOUT) if (ts < m_SessionTags.front ().creationTime + OUTGOING_TAGS_EXPIRATION_TIMEOUT)
@ -169,8 +169,10 @@ namespace garlic
tagFound = true; tagFound = true;
break; break;
} }
else else{
m_SessionTags.pop_front (); // remove expired tag m_SessionTags.pop_front (); // remove expired tag
LogPrint(eLogInfo, "Garlic: Remove expired tag");
}
} }
} }
// create message // create message
@ -247,7 +249,7 @@ namespace garlic
size_t GarlicRoutingSession::CreateGarlicPayload (uint8_t * payload, std::shared_ptr<const I2NPMessage> msg, UnconfirmedTags * newTags) size_t GarlicRoutingSession::CreateGarlicPayload (uint8_t * payload, std::shared_ptr<const I2NPMessage> msg, UnconfirmedTags * newTags)
{ {
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch (); uint64_t ts = i2p::util::getTime<std::chrono::milliseconds> (i2p::util::TimeType::milliseconds) ;
uint32_t msgID; uint32_t msgID;
RAND_bytes ((uint8_t *)&msgID, 4); RAND_bytes ((uint8_t *)&msgID, 4);
size_t size = 0; size_t size = 0;
@ -315,7 +317,7 @@ namespace garlic
size_t GarlicRoutingSession::CreateGarlicClove (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg, bool isDestination) size_t GarlicRoutingSession::CreateGarlicClove (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg, bool isDestination)
{ {
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch () + 8000; // 8 sec uint64_t ts = i2p::util::getTime<std::chrono::milliseconds> (i2p::util::TimeType::milliseconds) + 8000; // 8 sec
size_t size = 0; size_t size = 0;
if (isDestination) if (isDestination)
{ {
@ -373,7 +375,7 @@ namespace garlic
memcpy (buf + size, msg->GetBuffer (), msg->GetLength ()); memcpy (buf + size, msg->GetBuffer (), msg->GetLength ());
size += msg->GetLength (); size += msg->GetLength ();
// fill clove // fill clove
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch () + 8000; // 8 sec uint64_t ts = i2p::util::getTime<std::chrono::milliseconds> (i2p::util::TimeType::milliseconds) + 8000; // 8 sec
uint32_t cloveID; uint32_t cloveID;
RAND_bytes ((uint8_t *)&cloveID, 4); RAND_bytes ((uint8_t *)&cloveID, 4);
htobe32buf (buf + size, cloveID); // CloveID htobe32buf (buf + size, cloveID); // CloveID
@ -412,7 +414,7 @@ namespace garlic
{ {
if (key) if (key)
{ {
uint32_t ts = i2p::util::GetSecondsSinceEpoch (); uint32_t ts = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ;
m_Tags[SessionTag(tag, ts)] = std::make_shared<AESDecryption>(key); m_Tags[SessionTag(tag, ts)] = std::make_shared<AESDecryption>(key);
} }
} }
@ -480,7 +482,7 @@ namespace garlic
LogPrint (eLogError, "Garlic: Tag count ", tagCount, " exceeds length ", len); LogPrint (eLogError, "Garlic: Tag count ", tagCount, " exceeds length ", len);
return ; return ;
} }
uint32_t ts = i2p::util::GetSecondsSinceEpoch (); uint32_t ts = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ;
for (int i = 0; i < tagCount; i++) for (int i = 0; i < tagCount; i++)
m_Tags[SessionTag(buf + i*32, ts)] = decryption; m_Tags[SessionTag(buf + i*32, ts)] = decryption;
} }
@ -658,7 +660,7 @@ namespace garlic
void GarlicDestination::CleanupExpiredTags () void GarlicDestination::CleanupExpiredTags ()
{ {
// incoming // incoming
uint32_t ts = i2p::util::GetSecondsSinceEpoch (); uint32_t ts = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ;
int numExpiredTags = 0; int numExpiredTags = 0;
for (auto it = m_Tags.begin (); it != m_Tags.end ();) for (auto it = m_Tags.begin (); it != m_Tags.end ();)
{ {
@ -757,7 +759,7 @@ namespace garlic
std::string ident = GetIdentHash().ToBase32(); std::string ident = GetIdentHash().ToBase32();
std::string path = i2p::fs::DataDirPath("tags", (ident + ".tags")); std::string path = i2p::fs::DataDirPath("tags", (ident + ".tags"));
std::ofstream f (path, std::ofstream::binary | std::ofstream::out | std::ofstream::trunc); std::ofstream f (path, std::ofstream::binary | std::ofstream::out | std::ofstream::trunc);
uint32_t ts = i2p::util::GetSecondsSinceEpoch (); uint32_t ts = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ;
// 4 bytes timestamp, 32 bytes tag, 32 bytes key // 4 bytes timestamp, 32 bytes tag, 32 bytes key
for (auto it: m_Tags) for (auto it: m_Tags)
{ {
@ -774,7 +776,7 @@ namespace garlic
{ {
std::string ident = GetIdentHash().ToBase32(); std::string ident = GetIdentHash().ToBase32();
std::string path = i2p::fs::DataDirPath("tags", (ident + ".tags")); std::string path = i2p::fs::DataDirPath("tags", (ident + ".tags"));
uint32_t ts = i2p::util::GetSecondsSinceEpoch (); uint32_t ts = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ;
if (ts < i2p::fs::GetLastUpdateTime (path) + INCOMING_TAGS_EXPIRATION_TIMEOUT) if (ts < i2p::fs::GetLastUpdateTime (path) + INCOMING_TAGS_EXPIRATION_TIMEOUT)
{ {
// might contain non-expired tags // might contain non-expired tags
@ -816,7 +818,7 @@ namespace garlic
{ {
std::vector<std::string> files; std::vector<std::string> files;
i2p::fs::ReadDir (i2p::fs::DataDirPath("tags"), files); i2p::fs::ReadDir (i2p::fs::DataDirPath("tags"), files);
uint32_t ts = i2p::util::GetSecondsSinceEpoch (); uint32_t ts = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ;
for (auto it: files) for (auto it: files)
if (ts >= i2p::fs::GetLastUpdateTime (it) + INCOMING_TAGS_EXPIRATION_TIMEOUT) if (ts >= i2p::fs::GetLastUpdateTime (it) + INCOMING_TAGS_EXPIRATION_TIMEOUT)
i2p::fs::Remove (it); i2p::fs::Remove (it);

View file

@ -44,7 +44,7 @@ namespace i2p
SetTypeID (msgType); SetTypeID (msgType);
if (!replyMsgID) RAND_bytes ((uint8_t *)&replyMsgID, 4); if (!replyMsgID) RAND_bytes ((uint8_t *)&replyMsgID, 4);
SetMsgID (replyMsgID); SetMsgID (replyMsgID);
SetExpiration (i2p::util::GetMillisecondsSinceEpoch () + I2NP_MESSAGE_EXPIRATION_TIMEOUT); SetExpiration (i2p::util::getTime<std::chrono::milliseconds> (i2p::util::TimeType::milliseconds) + I2NP_MESSAGE_EXPIRATION_TIMEOUT);
UpdateSize (); UpdateSize ();
UpdateChks (); UpdateChks ();
} }
@ -54,13 +54,14 @@ namespace i2p
uint32_t msgID; uint32_t msgID;
RAND_bytes ((uint8_t *)&msgID, 4); RAND_bytes ((uint8_t *)&msgID, 4);
SetMsgID (msgID); SetMsgID (msgID);
SetExpiration (i2p::util::GetMillisecondsSinceEpoch () + I2NP_MESSAGE_EXPIRATION_TIMEOUT); SetExpiration (i2p::util::getTime<std::chrono::milliseconds> (i2p::util::TimeType::milliseconds) + I2NP_MESSAGE_EXPIRATION_TIMEOUT);
} }
bool I2NPMessage::IsExpired () const bool I2NPMessage::IsExpired () const
{ {
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
auto exp = GetExpiration (); auto exp = GetExpiration ();
auto ts = i2p::util::getTime<std::chrono::milliseconds> (i2p::util::TimeType::milliseconds) ;
return (ts > exp + I2NP_MESSAGE_CLOCK_SKEW) || (ts < exp - 3*I2NP_MESSAGE_CLOCK_SKEW); // check if expired or too far in future return (ts > exp + I2NP_MESSAGE_CLOCK_SKEW) || (ts < exp - 3*I2NP_MESSAGE_CLOCK_SKEW); // check if expired or too far in future
} }
@ -103,7 +104,7 @@ namespace i2p
if (msgID) if (msgID)
{ {
htobe32buf (buf + DELIVERY_STATUS_MSGID_OFFSET, msgID); htobe32buf (buf + DELIVERY_STATUS_MSGID_OFFSET, msgID);
htobe64buf (buf + DELIVERY_STATUS_TIMESTAMP_OFFSET, i2p::util::GetMillisecondsSinceEpoch ()); htobe64buf (buf + DELIVERY_STATUS_TIMESTAMP_OFFSET, i2p::util::getTime<std::chrono::milliseconds> (i2p::util::TimeType::milliseconds) );
} }
else // for SSU establishment else // for SSU establishment
{ {

View file

@ -73,7 +73,7 @@ namespace data
// process leases // process leases
m_ExpirationTime = 0; m_ExpirationTime = 0;
auto ts = i2p::util::GetMillisecondsSinceEpoch (); auto ts = i2p::util::getTime<std::chrono::milliseconds> (i2p::util::TimeType::milliseconds);
const uint8_t * leases = m_Buffer + size; const uint8_t * leases = m_Buffer + size;
for (int i = 0; i < num; i++) for (int i = 0; i < num; i++)
{ {
@ -165,7 +165,7 @@ namespace data
bool LeaseSet::ExpiresSoon(const uint64_t dlt, const uint64_t fudge) const bool LeaseSet::ExpiresSoon(const uint64_t dlt, const uint64_t fudge) const
{ {
auto now = i2p::util::GetMillisecondsSinceEpoch (); auto now = i2p::util::getTime<std::chrono::milliseconds> (i2p::util::TimeType::milliseconds);
if (fudge) now += rand() % fudge; if (fudge) now += rand() % fudge;
if (now >= m_ExpirationTime) return true; if (now >= m_ExpirationTime) return true;
return m_ExpirationTime - now <= dlt; return m_ExpirationTime - now <= dlt;
@ -178,7 +178,7 @@ namespace data
const std::vector<std::shared_ptr<const Lease> > LeaseSet::GetNonExpiredLeasesExcluding (LeaseInspectFunc exclude, bool withThreshold) const const std::vector<std::shared_ptr<const Lease> > LeaseSet::GetNonExpiredLeasesExcluding (LeaseInspectFunc exclude, bool withThreshold) const
{ {
auto ts = i2p::util::GetMillisecondsSinceEpoch (); auto ts = i2p::util::getTime<std::chrono::milliseconds> (i2p::util::TimeType::milliseconds);
std::vector<std::shared_ptr<const Lease> > leases; std::vector<std::shared_ptr<const Lease> > leases;
for (const auto& it: m_Leases) for (const auto& it: m_Leases)
{ {
@ -195,7 +195,7 @@ namespace data
bool LeaseSet::HasExpiredLeases () const bool LeaseSet::HasExpiredLeases () const
{ {
auto ts = i2p::util::GetMillisecondsSinceEpoch (); auto ts = i2p::util::getTime<std::chrono::milliseconds> (i2p::util::TimeType::milliseconds);
for (const auto& it: m_Leases) for (const auto& it: m_Leases)
if (ts >= it->endDate) return true; if (ts >= it->endDate) return true;
return false; return false;
@ -204,7 +204,7 @@ namespace data
bool LeaseSet::IsExpired () const bool LeaseSet::IsExpired () const
{ {
if (m_StoreLeases && IsEmpty ()) return true; if (m_StoreLeases && IsEmpty ()) return true;
auto ts = i2p::util::GetMillisecondsSinceEpoch (); auto ts = i2p::util::getTime<std::chrono::milliseconds> (i2p::util::TimeType::milliseconds);
return ts > m_ExpirationTime; return ts > m_ExpirationTime;
} }
@ -234,7 +234,7 @@ namespace data
offset++; offset++;
// leases // leases
m_Leases = m_Buffer + offset; m_Leases = m_Buffer + offset;
auto currentTime = i2p::util::GetMillisecondsSinceEpoch (); auto currentTime = i2p::util::getTime<std::chrono::milliseconds> (i2p::util::TimeType::milliseconds);
for (int i = 0; i < num; i++) for (int i = 0; i < num; i++)
{ {
memcpy (m_Buffer + offset, tunnels[i]->GetNextIdentHash (), 32); memcpy (m_Buffer + offset, tunnels[i]->GetNextIdentHash (), 32);
@ -262,7 +262,7 @@ namespace data
bool LocalLeaseSet::IsExpired () const bool LocalLeaseSet::IsExpired () const
{ {
auto ts = i2p::util::GetMillisecondsSinceEpoch (); auto ts = i2p::util::getTime<std::chrono::milliseconds> (i2p::util::TimeType::milliseconds);
return ts > m_ExpirationTime; return ts > m_ExpirationTime;
} }

View file

@ -28,7 +28,7 @@ namespace data
bool isUpdated; // trasient bool isUpdated; // trasient
/* return true if this lease expires within t millisecond + fudge factor */ /* return true if this lease expires within t millisecond + fudge factor */
bool ExpiresWithin( const uint64_t t, const uint64_t fudge = 1000 ) const { bool ExpiresWithin( const uint64_t t, const uint64_t fudge = 1000 ) const {
auto expire = i2p::util::GetMillisecondsSinceEpoch (); auto expire = i2p::util::getTime<std::chrono::milliseconds> (i2p::util::TimeType::milliseconds);
if(fudge) expire += rand() % fudge; if(fudge) expire += rand() % fudge;
if (endDate < expire) return true; if (endDate < expire) return true;
return (endDate - expire) < t; return (endDate - expire) < t;

View file

@ -128,7 +128,7 @@ namespace transport
void NTCPSession::ServerLogin () void NTCPSession::ServerLogin ()
{ {
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); m_LastActivityTimestamp = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds);
// receive Phase1 // receive Phase1
boost::asio::async_read (m_Socket, boost::asio::buffer(&m_Establisher->phase1, sizeof (NTCPPhase1)), boost::asio::transfer_all (), boost::asio::async_read (m_Socket, boost::asio::buffer(&m_Establisher->phase1, sizeof (NTCPPhase1)), boost::asio::transfer_all (),
std::bind(&NTCPSession::HandlePhase1Received, shared_from_this (), std::bind(&NTCPSession::HandlePhase1Received, shared_from_this (),
@ -195,7 +195,7 @@ namespace transport
memcpy (xy, m_Establisher->phase1.pubKey, 256); memcpy (xy, m_Establisher->phase1.pubKey, 256);
memcpy (xy + 256, y, 256); memcpy (xy + 256, y, 256);
SHA256(xy, 512, m_Establisher->phase2.encrypted.hxy); SHA256(xy, 512, m_Establisher->phase2.encrypted.hxy);
uint32_t tsB = htobe32 (i2p::util::GetSecondsSinceEpoch ()); uint32_t tsB = htobe32 (i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) );
memcpy (m_Establisher->phase2.encrypted.timestamp, &tsB, 4); memcpy (m_Establisher->phase2.encrypted.timestamp, &tsB, 4);
RAND_bytes (m_Establisher->phase2.encrypted.filler, 12); RAND_bytes (m_Establisher->phase2.encrypted.filler, 12);
@ -279,7 +279,7 @@ namespace transport
htobe16buf (buf, keys.GetPublic ()->GetFullLen ()); htobe16buf (buf, keys.GetPublic ()->GetFullLen ());
buf += 2; buf += 2;
buf += i2p::context.GetIdentity ()->ToBuffer (buf, NTCP_BUFFER_SIZE); buf += i2p::context.GetIdentity ()->ToBuffer (buf, NTCP_BUFFER_SIZE);
uint32_t tsA = htobe32 (i2p::util::GetSecondsSinceEpoch ()); uint32_t tsA = htobe32 (i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) );
htobuf32(buf,tsA); htobuf32(buf,tsA);
buf += 4; buf += 4;
size_t signatureLen = keys.GetPublic ()->GetSignatureLen (); size_t signatureLen = keys.GetPublic ()->GetSignatureLen ();
@ -389,13 +389,15 @@ namespace transport
buf += paddingLen; buf += paddingLen;
// check timestamp // check timestamp
auto ts = i2p::util::GetSecondsSinceEpoch (); auto ts = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ;
uint32_t tsA1 = be32toh (tsA); uint32_t tsA1 = be32toh (tsA);
if (tsA1 < ts - NTCP_CLOCK_SKEW || tsA1 > ts + NTCP_CLOCK_SKEW) if (tsA1 < ts - NTCP_CLOCK_SKEW || tsA1 > ts + NTCP_CLOCK_SKEW)
{ {
LogPrint (eLogError, "NTCP: Phase3 time difference ", ts - tsA1, " exceeds clock skew"); if( !i2p::util::timeCorrecting(tsA1, ts, NTCP_CLOCK_SKEW, "NTCP: Phase3 time difference ") ){
Terminate (); LogPrint (eLogError, "NTCP: Phase3 time difference ", ts - tsA1, " exceeds clock skew");
return; Terminate ();
return;
}
} }
// check signature // check signature
@ -460,8 +462,10 @@ namespace transport
if (ecode) if (ecode)
{ {
LogPrint (eLogError, "NTCP: Phase 4 read error: ", ecode.message (), ". Check your clock"); LogPrint (eLogError, "NTCP: Phase 4 read error: ", ecode.message (), ". Check your clock");
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)
{ {
LogPrint(eLogError, "NTCP: Phase 4 read error: ", "Close router");
// this router doesn't like us // this router doesn't like us
i2p::data::netdb.SetUnreachable (GetRemoteIdentity ()->GetIdentHash (), true); i2p::data::netdb.SetUnreachable (GetRemoteIdentity ()->GetIdentHash (), true);
Terminate (); Terminate ();
@ -473,12 +477,16 @@ namespace transport
// check timestamp // check timestamp
uint32_t tsB = bufbe32toh (m_Establisher->phase2.encrypted.timestamp); uint32_t tsB = bufbe32toh (m_Establisher->phase2.encrypted.timestamp);
auto ts = i2p::util::GetSecondsSinceEpoch (); auto ts = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ;
if (tsB < ts - NTCP_CLOCK_SKEW || tsB > ts + NTCP_CLOCK_SKEW) if (tsB < ts - NTCP_CLOCK_SKEW || tsB > ts + NTCP_CLOCK_SKEW)
{ {
LogPrint (eLogError, "NTCP: Phase4 time difference ", ts - tsB, " exceeds clock skew");
Terminate (); if( !i2p::util::timeCorrecting(tsB, ts, NTCP_CLOCK_SKEW, "NTCP: Phase3 time difference ") )
return; {
LogPrint (eLogError, "NTCP: Phase4 time difference ", ts - tsB, " exceeds clock skew");
Terminate ();
return;
}
} }
// verify signature // verify signature
@ -589,7 +597,7 @@ namespace transport
} }
m_Handler.Flush (); m_Handler.Flush ();
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); m_LastActivityTimestamp = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds);
Receive (); Receive ();
} }
} }
@ -620,7 +628,7 @@ namespace transport
else else
{ {
// timestamp // timestamp
int diff = (int)bufbe32toh (buf + 2) - (int)i2p::util::GetSecondsSinceEpoch (); int diff = (int)bufbe32toh (buf + 2) - (int)i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ;
LogPrint (eLogInfo, "NTCP: Timestamp. Time difference ", diff, " seconds"); LogPrint (eLogInfo, "NTCP: Timestamp. Time difference ", diff, " seconds");
return true; return true;
} }
@ -638,7 +646,7 @@ namespace transport
htobe32buf (checksum, adler32 (adler32 (0, Z_NULL, 0), m_NextMessage->GetBuffer () - 2, m_NextMessageOffset - 4)); htobe32buf (checksum, adler32 (adler32 (0, Z_NULL, 0), m_NextMessage->GetBuffer () - 2, m_NextMessageOffset - 4));
if (!memcmp (m_NextMessage->GetBuffer () - 2 + m_NextMessageOffset - 4, checksum, 4)) if (!memcmp (m_NextMessage->GetBuffer () - 2 + m_NextMessageOffset - 4, checksum, 4))
{ {
if (!m_NextMessage->IsExpired ()) if (!m_NextMessage->IsExpired ()) // TODO: look to
{ {
#ifdef WITH_EVENTS #ifdef WITH_EVENTS
QueueIntEvent("transport.recvmsg", GetIdentHashBase64(), 1); QueueIntEvent("transport.recvmsg", GetIdentHashBase64(), 1);
@ -682,7 +690,7 @@ namespace transport
sendBuffer = m_TimeSyncBuffer; sendBuffer = m_TimeSyncBuffer;
len = 4; len = 4;
htobuf16(sendBuffer, 0); htobuf16(sendBuffer, 0);
htobe32buf (sendBuffer + 2, i2p::util::GetSecondsSinceEpoch ()); htobe32buf (sendBuffer + 2, i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) );
} }
int rem = (len + 6) & 0x0F; // %16 int rem = (len + 6) & 0x0F; // %16
int padding = 0; int padding = 0;
@ -722,7 +730,7 @@ namespace transport
} }
else else
{ {
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); m_LastActivityTimestamp = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds);
m_NumSentBytes += bytes_transferred; m_NumSentBytes += bytes_transferred;
i2p::transport::transports.UpdateSentBytes (bytes_transferred); i2p::transport::transports.UpdateSentBytes (bytes_transferred);
if (!m_SendQueue.empty()) if (!m_SendQueue.empty())
@ -1271,7 +1279,7 @@ namespace transport
{ {
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)
{ {
auto ts = i2p::util::GetSecondsSinceEpoch (); auto ts = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds);
// established // established
for (auto& it: m_NTCPSessions) for (auto& it: m_NTCPSessions)
if (it.second->IsTerminationTimeoutExpired (ts)) if (it.second->IsTerminationTimeoutExpired (ts))

View file

@ -20,7 +20,7 @@ namespace data
msg = i2p::CreateRouterInfoDatabaseLookupMsg(m_Destination, i2p::context.GetIdentHash(), 0, m_IsExploratory, &m_ExcludedPeers); msg = i2p::CreateRouterInfoDatabaseLookupMsg(m_Destination, i2p::context.GetIdentHash(), 0, m_IsExploratory, &m_ExcludedPeers);
if(router) if(router)
m_ExcludedPeers.insert (router->GetIdentHash ()); m_ExcludedPeers.insert (router->GetIdentHash ());
m_CreationTime = i2p::util::GetSecondsSinceEpoch (); m_CreationTime = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds);
return msg; return msg;
} }
@ -29,7 +29,7 @@ namespace data
auto msg = i2p::CreateRouterInfoDatabaseLookupMsg (m_Destination, auto msg = i2p::CreateRouterInfoDatabaseLookupMsg (m_Destination,
i2p::context.GetRouterInfo ().GetIdentHash () , 0, false, &m_ExcludedPeers); i2p::context.GetRouterInfo ().GetIdentHash () , 0, false, &m_ExcludedPeers);
m_ExcludedPeers.insert (floodfill); m_ExcludedPeers.insert (floodfill);
m_CreationTime = i2p::util::GetSecondsSinceEpoch (); m_CreationTime = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds);
return msg; return msg;
} }
@ -111,7 +111,7 @@ namespace data
void NetDbRequests::ManageRequests () void NetDbRequests::ManageRequests ()
{ {
uint64_t ts = i2p::util::GetSecondsSinceEpoch (); uint64_t ts = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds);
std::unique_lock<std::mutex> l(m_RequestedDestinationsMutex); std::unique_lock<std::mutex> l(m_RequestedDestinationsMutex);
for (auto it = m_RequestedDestinations.begin (); it != m_RequestedDestinations.end ();) for (auto it = m_RequestedDestinations.begin (); it != m_RequestedDestinations.end ();)
{ {

View file

@ -32,7 +32,7 @@ namespace transport
auto address = i2p::context.GetRouterInfo ().GetSSUAddress (false); auto address = i2p::context.GetRouterInfo ().GetSSUAddress (false);
if (address) m_IntroKey = address->ssu->key; if (address) m_IntroKey = address->ssu->key;
} }
m_CreationTime = i2p::util::GetSecondsSinceEpoch (); m_CreationTime =i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ;
} }
SSUSession::~SSUSession () SSUSession::~SSUSession ()
@ -98,7 +98,7 @@ namespace transport
{ {
if (!len) return; // ignore zero-length packets if (!len) return; // ignore zero-length packets
if (m_State == eSessionStateEstablished) if (m_State == eSessionStateEstablished)
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); m_LastActivityTimestamp =i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ;
if (m_IsSessionKey && Validate (buf, len, m_MacKey)) // try session key first if (m_IsSessionKey && Validate (buf, len, m_MacKey)) // try session key first
DecryptSessionKey (buf, len); DecryptSessionKey (buf, len);
@ -276,13 +276,13 @@ namespace transport
payload += 4; // relayTag payload += 4; // relayTag
if (i2p::context.GetStatus () == eRouterStatusTesting) if (i2p::context.GetStatus () == eRouterStatusTesting)
{ {
auto ts = i2p::util::GetSecondsSinceEpoch (); auto ts = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ;
uint32_t signedOnTime = bufbe32toh(payload); uint32_t signedOnTime = bufbe32toh(payload);
if (signedOnTime < ts - SSU_CLOCK_SKEW || signedOnTime > ts + SSU_CLOCK_SKEW) if (signedOnTime < ts - SSU_CLOCK_SKEW || signedOnTime > ts + SSU_CLOCK_SKEW)
{ {
LogPrint (eLogError, "SSU: clock skew detected ", (int)ts - signedOnTime, ". Check your clock"); i2p::util::timeCorrecting(signedOnTime, ts, SSU_CLOCK_SKEW, "SSU: clock skew detected ");
i2p::context.SetError (eRouterErrorClockSkew);
} }
} }
payload += 4; // signed on time payload += 4; // signed on time
// decrypt signature // decrypt signature
@ -324,7 +324,7 @@ namespace transport
SetRemoteIdentity (existing ? existing->GetRouterIdentity () : identity); SetRemoteIdentity (existing ? existing->GetRouterIdentity () : identity);
m_Data.UpdatePacketSize (m_RemoteIdentity->GetIdentHash ()); m_Data.UpdatePacketSize (m_RemoteIdentity->GetIdentHash ());
payload += identitySize; // identity payload += identitySize; // identity
auto ts = i2p::util::GetSecondsSinceEpoch (); auto ts = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ;
uint32_t signedOnTime = bufbe32toh(payload); uint32_t signedOnTime = bufbe32toh(payload);
if (signedOnTime < ts - SSU_CLOCK_SKEW || signedOnTime > ts + SSU_CLOCK_SKEW) if (signedOnTime < ts - SSU_CLOCK_SKEW || signedOnTime > ts + SSU_CLOCK_SKEW)
{ {
@ -469,7 +469,7 @@ namespace transport
} }
htobe32buf (payload, m_SentRelayTag); htobe32buf (payload, m_SentRelayTag);
payload += 4; // relay tag payload += 4; // relay tag
htobe32buf (payload, i2p::util::GetSecondsSinceEpoch ()); // signed on time htobe32buf (payload,i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ); // signed on time
payload += 4; payload += 4;
s.Insert (payload - 8, 4); // relayTag s.Insert (payload - 8, 4); // relayTag
// we have to store this signed data for session confirmed // we have to store this signed data for session confirmed
@ -510,7 +510,7 @@ namespace transport
payload += 2; // cursize payload += 2; // cursize
i2p::context.GetIdentity ()->ToBuffer (payload, identLen); i2p::context.GetIdentity ()->ToBuffer (payload, identLen);
payload += identLen; payload += identLen;
uint32_t signedOnTime = i2p::util::GetSecondsSinceEpoch (); uint32_t signedOnTime =i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ;
htobe32buf (payload, signedOnTime); // signed on time htobe32buf (payload, signedOnTime); // signed on time
payload += 4; payload += 4;
auto signatureLen = i2p::context.GetIdentity ()->GetSignatureLen (); auto signatureLen = i2p::context.GetIdentity ()->GetSignatureLen ();
@ -721,7 +721,7 @@ namespace transport
SSUHeader * header = (SSUHeader *)buf; SSUHeader * header = (SSUHeader *)buf;
memcpy (header->iv, iv, 16); memcpy (header->iv, iv, 16);
header->flag = flag | (payloadType << 4); // MSB is 0 header->flag = flag | (payloadType << 4); // MSB is 0
htobe32buf (header->time, i2p::util::GetSecondsSinceEpoch ()); htobe32buf (header->time,i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) );
uint8_t * encrypted = &header->flag; uint8_t * encrypted = &header->flag;
uint16_t encryptedLen = len - (encrypted - buf); uint16_t encryptedLen = len - (encrypted - buf);
i2p::crypto::CBCEncryption encryption; i2p::crypto::CBCEncryption encryption;
@ -745,7 +745,7 @@ namespace transport
RAND_bytes (header->iv, 16); // random iv RAND_bytes (header->iv, 16); // random iv
m_SessionKeyEncryption.SetIV (header->iv); m_SessionKeyEncryption.SetIV (header->iv);
header->flag = payloadType << 4; // MSB is 0 header->flag = payloadType << 4; // MSB is 0
htobe32buf (header->time, i2p::util::GetSecondsSinceEpoch ()); htobe32buf (header->time,i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) );
uint8_t * encrypted = &header->flag; uint8_t * encrypted = &header->flag;
uint16_t encryptedLen = len - (encrypted - buf); uint16_t encryptedLen = len - (encrypted - buf);
m_SessionKeyEncryption.Encrypt (encrypted, encryptedLen, encrypted); m_SessionKeyEncryption.Encrypt (encrypted, encryptedLen, encrypted);
@ -907,7 +907,7 @@ namespace transport
SendPeerTest (); SendPeerTest ();
if (m_SentRelayTag) if (m_SentRelayTag)
m_Server.AddRelay (m_SentRelayTag, shared_from_this ()); m_Server.AddRelay (m_SentRelayTag, shared_from_this ());
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); m_LastActivityTimestamp = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ;
} }
void SSUSession::Failed () void SSUSession::Failed ()
@ -1149,7 +1149,7 @@ namespace transport
FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, 48); FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, 48);
Send (buf, 48); Send (buf, 48);
LogPrint (eLogDebug, "SSU: keep-alive sent"); LogPrint (eLogDebug, "SSU: keep-alive sent");
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); m_LastActivityTimestamp =i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds) ;
} }
} }

View file

@ -1,9 +1,13 @@
#include <inttypes.h> #include <inttypes.h>
#include <string.h> #include <string.h>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <boost/algorithm/string.hpp>
#include "Log.h" #include "Log.h"
#include "I2PEndian.h" #include "I2PEndian.h"
#include "Timestamp.h" #include "Timestamp.h"
#include"RouterContext.h"
#ifdef WIN32 #ifdef WIN32
#ifndef _WIN64 #ifndef _WIN64
@ -15,51 +19,93 @@ namespace i2p
{ {
namespace util namespace util
{ {
static int64_t g_TimeOffset = 0; // in seconds int64_t g_TimeOffset;
static inline void setTimeOffset(int64_t ts){g_TimeOffset=ts;}
void SyncTimeWithNTP (const std::string& address)
bool timeCorrecting(uint32_t signedOnTime, uint32_t ts, uint32_t skew, const char * ErrorMsg){
bool Time_Correcting; i2p::config::GetOption("time.correcting", Time_Correcting);
if( !Time_Correcting ){
LogPrint (eLogError, ErrorMsg, (int)ts - signedOnTime, ". Check your clock");
i2p::context.SetError (eRouterErrorClockSkew);
return false;
}
if (signedOnTime > 2208988800U) signedOnTime -= 2208988800U; // 1/1/1970 from 1/1/1900
LogPrint (eLogWarning, "I2Pd Time correcting: timeCorrecting ");
i2p::util::setTimeOffset( signedOnTime < ts - skew ? -signedOnTime : signedOnTime );
return true;
}
//TODO: ...Syncing with option
bool SyncTimeWithNTP (void)
{ {
boost::asio::io_service service;
boost::asio::ip::udp::resolver::query query (boost::asio::ip::udp::v4 (), address, "ntp"); bool UseNTP; i2p::config::GetOption("time.use_ntp", UseNTP);
boost::system::error_code ec; if(!UseNTP) return false;
auto it = boost::asio::ip::udp::resolver (service).resolve (query, ec);
if (!ec && it != boost::asio::ip::udp::resolver::iterator()) std::string address; i2p::config::GetOption("time.ntp_server", address);
{
auto ep = (*it).endpoint (); // take first one std::vector<std::string> addresses;
boost::asio::ip::udp::socket socket (service); boost::split(addresses, address, boost::is_any_of(","));
socket.open (boost::asio::ip::udp::v4 (), ec);
if (!ec) for ( auto addr : addresses ){
LogPrint (eLogInfo, "I2Pd Time Correcting: SyncingWithNTP with server ", addr);
boost::asio::io_service service;
boost::asio::ip::udp::resolver::query query (boost::asio::ip::udp::v4 (), addr, "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())
{ {
uint8_t buf[48];// 48 bytes NTP request/response auto ep = (*it).endpoint (); // take first one
memset (buf, 0, 48); boost::asio::ip::udp::socket socket (service);
htobe32buf (buf, (3 << 27) | (3 << 24)); // RFC 4330 socket.open (boost::asio::ip::udp::v4 (), ec);
size_t len = 0; if (!ec)
try
{ {
socket.send_to (boost::asio::buffer (buf, 48), ep); uint8_t buf[48];// 48 bytes NTP request/response
int i = 0; memset (buf, 0, 48);
while (!socket.available() && i < 10) // 10 seconds max htobe32buf (buf, (3 << 27) | (3 << 24)); // RFC 4330
size_t len = 0;
try
{ {
std::this_thread::sleep_for (std::chrono::seconds(1)); socket.send_to (boost::asio::buffer (buf, 48), ep);
i++; int i = 0;
} while (!socket.available() && i < NTPMaxTimeConnecting) // 10 seconds max
if (socket.available ()) {
len = socket.receive_from (boost::asio::buffer (buf, 48), ep); std::this_thread::sleep_for (std::chrono::seconds(1));
} i++;
catch (std::exception& e) }
{ if( i == NTPMaxTimeConnecting ) throw( std::runtime_error("timeout" ) );
LogPrint (eLogError, "NTP error: ", e.what ()); if (socket.available ())
} len = socket.receive_from (boost::asio::buffer (buf, 48), ep);
if (len >= 8) if(len < 8) throw( std::runtime_error("len of answer not equal 8") );
{
auto ourTs = GetSecondsSinceEpoch (); auto ourTs = GetSecondsSinceEpoch ();
uint32_t ts = bufbe32toh (buf + 32); uint32_t ts = bufbe32toh (buf + 32);
if (ts > 2208988800U) ts -= 2208988800U; // 1/1/1970 from 1/1/1900 LogPrint (eLogDebug, "I2Pd Time Correcting: SyncingWithNTP ",ourTs, " < our not our > ", ts);
g_TimeOffset = ts - ourTs; if (ts > 2208988800U) ts -= 2208988800U; // 1/1/1970 from 1/1/1900
LogPrint (eLogInfo, address, " time offset from system time is ", g_TimeOffset, " seconds");
setTimeOffset( ts - ourTs );
LogPrint (eLogDebug, "I2Pd Time Correcting: ", addr, " time offset from system time is ", g_TimeOffset, " seconds");
break;
}catch (std::exception& e)
{
LogPrint (eLogError, "NTP error: ", e.what ());
}
} }
} }
} }
return true;
} }
} }
} }

View file

@ -3,30 +3,83 @@
#include <inttypes.h> #include <inttypes.h>
#include <chrono> #include <chrono>
#include"Config.h"
#include "Log.h"
namespace i2p namespace i2p
{ {
namespace util namespace util
{
inline uint64_t GetMillisecondsSinceEpoch ()
{ {
return std::chrono::duration_cast<std::chrono::milliseconds>( constexpr char NTPMaxTimeConnecting = 15;
std::chrono::system_clock::now().time_since_epoch()).count (); extern int64_t g_TimeOffset; // in seconds
}
inline uint32_t GetHoursSinceEpoch () enum class TimeType{
{ milliseconds, seconds, hours
return std::chrono::duration_cast<std::chrono::hours>( };
std::chrono::system_clock::now().time_since_epoch()).count ();
}
inline uint64_t GetSecondsSinceEpoch () template <typename Type> inline uint64_t getTime(void)
{ {
return std::chrono::duration_cast<std::chrono::seconds>( return std::chrono::duration_cast<Type>(
std::chrono::system_clock::now().time_since_epoch()).count (); std::chrono::system_clock::now().time_since_epoch()).count ();
}
template <typename Type> auto getTime(TimeType tt) -> decltype(getTime<Type>()){
LogPrint (eLogDebug, "I2Pd Time Correcting: offset = ", g_TimeOffset );
bool Time_Correcting, Time_UseNTP;
i2p::config::GetOption("time.correcting", Time_Correcting);
i2p::config::GetOption("time.use_ntp", Time_UseNTP);
if(Time_Correcting || Time_UseNTP)
LogPrint (eLogDebug, "I2Pd Time Correcting: Return time with offset ", getTime<Type>() + g_TimeOffset );
else
LogPrint(eLogDebug, "I2Pd Time Correcting: return real time");
if(Time_Correcting || Time_UseNTP){
auto tmpTime = getTime<Type>() ;
switch(tt){
case TimeType::milliseconds:
return tmpTime+g_TimeOffset*1000;
case TimeType::seconds:
return tmpTime+g_TimeOffset;
break;
case TimeType::hours:
if(tmpTime)
return tmpTime + g_TimeOffset/120;
break;
}
}
return getTime<Type>();
}
bool timeCorrecting(uint32_t signedOnTime, uint32_t ts, uint32_t skew, const char * ErrorMsg);
bool SyncTimeWithNTP (void);
inline uint64_t GetSecondsSinceEpoch ()
{
return getTime<std::chrono::seconds>();
}
inline uint64_t GetMillisecondsSinceEpoch ()
{
return getTime<std::chrono::milliseconds>();
}
inline uint32_t GetHoursSinceEpoch ()
{
return getTime<std::chrono::hours>();
}
} }
} }
}
#endif #endif

View file

@ -345,7 +345,7 @@ namespace client
auto l = version.length () + 1 + 8; auto l = version.length () + 1 + 8;
uint8_t * payload = new uint8_t[l]; uint8_t * payload = new uint8_t[l];
// set date // set date
auto ts = i2p::util::GetMillisecondsSinceEpoch (); auto ts = i2p::util::getTime<std::chrono::milliseconds> (i2p::util::TimeType::milliseconds);
htobe64buf (payload, ts); htobe64buf (payload, ts);
// echo vesrion back // echo vesrion back
PutString (payload + 8, l - 8, version); PutString (payload + 8, l - 8, version);

View file

@ -60,7 +60,7 @@ namespace client
void I2PService::AddReadyCallback(ReadyCallback cb) void I2PService::AddReadyCallback(ReadyCallback cb)
{ {
uint32_t now = i2p::util::GetSecondsSinceEpoch(); uint32_t now = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds);
uint32_t tm = now + m_ConnectTimeout; uint32_t tm = now + m_ConnectTimeout;
LogPrint(eLogDebug, "I2PService::AddReadyCallback() ", tm, " ", now); LogPrint(eLogDebug, "I2PService::AddReadyCallback() ", tm, " ", now);
m_ReadyCallbacks.push_back({cb, tm}); m_ReadyCallbacks.push_back({cb, tm});
@ -83,7 +83,7 @@ namespace client
else if(!m_LocalDestination->IsReady()) else if(!m_LocalDestination->IsReady())
{ {
// expire timed out requests // expire timed out requests
uint32_t now = i2p::util::GetSecondsSinceEpoch (); uint32_t now = i2p::util::getTime<std::chrono::seconds> (i2p::util::TimeType::seconds);
auto itr = m_ReadyCallbacks.begin(); auto itr = m_ReadyCallbacks.begin();
while(itr != m_ReadyCallbacks.end()) while(itr != m_ReadyCallbacks.end())
{ {

View file

@ -604,12 +604,12 @@ namespace client
std::lock_guard<std::mutex> lock(m_SessionsMutex); std::lock_guard<std::mutex> lock(m_SessionsMutex);
auto session = ObtainUDPSession(from, toPort, fromPort); auto session = ObtainUDPSession(from, toPort, fromPort);
session->IPSocket.send_to(boost::asio::buffer(buf, len), m_RemoteEndpoint); session->IPSocket.send_to(boost::asio::buffer(buf, len), m_RemoteEndpoint);
session->LastActivity = i2p::util::GetMillisecondsSinceEpoch(); session->LastActivity = i2p::util::getTime<std::chrono::milliseconds> (i2p::util::TimeType::milliseconds);
} }
void I2PUDPServerTunnel::ExpireStale(const uint64_t delta) { void I2PUDPServerTunnel::ExpireStale(const uint64_t delta) {
std::lock_guard<std::mutex> lock(m_SessionsMutex); std::lock_guard<std::mutex> lock(m_SessionsMutex);
uint64_t now = i2p::util::GetMillisecondsSinceEpoch(); uint64_t now = i2p::util::getTime<std::chrono::milliseconds> (i2p::util::TimeType::milliseconds);
auto itr = m_Sessions.begin(); auto itr = m_Sessions.begin();
while(itr != m_Sessions.end()) { while(itr != m_Sessions.end()) {
if(now - (*itr)->LastActivity >= delta ) if(now - (*itr)->LastActivity >= delta )
@ -621,7 +621,7 @@ namespace client
void I2PUDPClientTunnel::ExpireStale(const uint64_t delta) { void I2PUDPClientTunnel::ExpireStale(const uint64_t delta) {
std::lock_guard<std::mutex> lock(m_SessionsMutex); std::lock_guard<std::mutex> lock(m_SessionsMutex);
uint64_t now = i2p::util::GetMillisecondsSinceEpoch(); uint64_t now = i2p::util::getTime<std::chrono::milliseconds> (i2p::util::TimeType::milliseconds);
std::vector<uint16_t> removePorts; std::vector<uint16_t> removePorts;
for (const auto & s : m_Sessions) { for (const auto & s : m_Sessions) {
if (now - s.second.second >= delta) if (now - s.second.second >= delta)
@ -666,7 +666,7 @@ namespace client
m_Destination(localDestination->GetDatagramDestination()), m_Destination(localDestination->GetDatagramDestination()),
IPSocket(localDestination->GetService(), localEndpoint), IPSocket(localDestination->GetService(), localEndpoint),
SendEndpoint(endpoint), SendEndpoint(endpoint),
LastActivity(i2p::util::GetMillisecondsSinceEpoch()), LastActivity(i2p::util::getTime<std::chrono::milliseconds> (i2p::util::TimeType::milliseconds)),
LocalPort(ourPort), LocalPort(ourPort),
RemotePort(theirPort) RemotePort(theirPort)
{ {
@ -685,7 +685,7 @@ namespace client
if(!ecode) if(!ecode)
{ {
LogPrint(eLogDebug, "UDPSession: forward ", len, "B from ", FromEndpoint); LogPrint(eLogDebug, "UDPSession: forward ", len, "B from ", FromEndpoint);
LastActivity = i2p::util::GetMillisecondsSinceEpoch(); LastActivity = i2p::util::getTime<std::chrono::milliseconds> (i2p::util::TimeType::milliseconds);
m_Destination->SendDatagramTo(m_Buffer, len, Identity, LocalPort, RemotePort); m_Destination->SendDatagramTo(m_Buffer, len, Identity, LocalPort, RemotePort);
Receive(); Receive();
} else { } else {
@ -795,7 +795,7 @@ namespace client
LogPrint(eLogDebug, "UDP Client: send ", transferred, " to ", m_RemoteIdent->ToBase32(), ":", RemotePort); LogPrint(eLogDebug, "UDP Client: send ", transferred, " to ", m_RemoteIdent->ToBase32(), ":", RemotePort);
m_LocalDest->GetDatagramDestination()->SendDatagramTo(m_RecvBuff, transferred, *m_RemoteIdent, remotePort, RemotePort); m_LocalDest->GetDatagramDestination()->SendDatagramTo(m_RecvBuff, transferred, *m_RemoteIdent, remotePort, RemotePort);
// mark convo as active // mark convo as active
m_Sessions[remotePort].second = i2p::util::GetMillisecondsSinceEpoch(); m_Sessions[remotePort].second = i2p::util::getTime<std::chrono::milliseconds> (i2p::util::TimeType::milliseconds);
RecvFromLocal(); RecvFromLocal();
} }
@ -837,7 +837,7 @@ namespace client
LogPrint(eLogDebug, "UDP Client: got ", len, "B from ", from.GetIdentHash().ToBase32()); LogPrint(eLogDebug, "UDP Client: got ", len, "B from ", from.GetIdentHash().ToBase32());
m_LocalSocket.send_to(boost::asio::buffer(buf, len), itr->second.first); m_LocalSocket.send_to(boost::asio::buffer(buf, len), itr->second.first);
// mark convo as active // mark convo as active
itr->second.second = i2p::util::GetMillisecondsSinceEpoch(); itr->second.second = i2p::util::getTime<std::chrono::milliseconds> (i2p::util::TimeType::milliseconds);
} }
} }
else else