i2pd/libi2pd/TransportSession.h

203 lines
6.7 KiB
C
Raw Normal View History

/*
* Copyright (c) 2013-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
2014-10-20 20:09:59 +00:00
#ifndef TRANSPORT_SESSION_H__
#define TRANSPORT_SESSION_H__
#include <inttypes.h>
#include <iostream>
#include <memory>
2015-01-21 02:05:57 +00:00
#include <vector>
2020-04-01 13:54:10 +00:00
#include <mutex>
#include "Identity.h"
2015-11-03 14:15:49 +00:00
#include "Crypto.h"
#include "RouterInfo.h"
#include "I2NPProtocol.h"
#include "Timestamp.h"
2014-10-20 20:09:59 +00:00
namespace i2p
{
namespace transport
{
const size_t IPV4_HEADER_SIZE = 20;
const size_t IPV6_HEADER_SIZE = 40;
const size_t UDP_HEADER_SIZE = 8;
class SignedData
{
public:
2015-11-03 14:15:49 +00:00
SignedData () {}
2018-01-06 03:48:51 +00:00
SignedData (const SignedData& other)
2015-11-03 14:15:49 +00:00
{
m_Stream << other.m_Stream.rdbuf ();
2018-01-06 03:48:51 +00:00
}
2022-06-21 12:12:41 +00:00
void Reset ()
{
m_Stream.str("");
}
2018-01-06 03:48:51 +00:00
void Insert (const uint8_t * buf, size_t len)
{
m_Stream.write ((char *)buf, len);
}
template<typename T>
void Insert (T t)
{
2018-01-06 03:48:51 +00:00
m_Stream.write ((char *)&t, sizeof (T));
}
2015-11-03 14:15:49 +00:00
bool Verify (std::shared_ptr<const i2p::data::IdentityEx> ident, const uint8_t * signature) const
{
2018-01-06 03:48:51 +00:00
return ident->Verify ((const uint8_t *)m_Stream.str ().c_str (), m_Stream.str ().size (), signature);
}
void Sign (const i2p::data::PrivateKeys& keys, uint8_t * signature) const
{
2018-01-06 03:48:51 +00:00
keys.Sign ((const uint8_t *)m_Stream.str ().c_str (), m_Stream.str ().size (), signature);
}
private:
2018-01-06 03:48:51 +00:00
std::stringstream m_Stream;
2018-01-06 03:48:51 +00:00
};
2023-03-29 19:54:53 +00:00
const int64_t TRANSPORT_SESSION_SLOWNESS_THRESHOLD = 500; // in milliseconds
const int64_t TRANSPORT_SESSION_MAX_HANDSHAKE_INTERVAL = 10000; // in milliseconds
2023-10-15 12:31:55 +00:00
const uint64_t TRANSPORT_SESSION_BANDWIDTH_UPDATE_MIN_INTERVAL = 5; // in seconds
2014-10-20 20:09:59 +00:00
class TransportSession
{
public:
2018-01-06 03:48:51 +00:00
TransportSession (std::shared_ptr<const i2p::data::RouterInfo> router, int terminationTimeout):
2023-10-15 12:31:55 +00:00
m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout), m_HandshakeInterval (0),
m_SendQueueSize (0), m_NumSentBytes (0), m_NumReceivedBytes (0),
m_LastBandWidthUpdateNumSentBytes (0), m_LastBandWidthUpdateNumReceivedBytes (0),
m_LastActivityTimestamp (i2p::util::GetSecondsSinceEpoch ()),
m_LastBandwidthUpdateTimestamp (m_LastActivityTimestamp), m_InBandwidth (0), m_OutBandwidth (0)
{
2015-11-03 14:15:49 +00:00
if (router)
m_RemoteIdentity = router->GetRouterIdentity ();
m_CreationTime = m_LastActivityTimestamp;
}
2015-11-03 14:15:49 +00:00
virtual ~TransportSession () {};
2015-02-07 01:53:48 +00:00
virtual void Done () = 0;
2016-10-20 13:12:15 +00:00
2016-11-01 17:57:25 +00:00
std::string GetIdentHashBase64() const { return m_RemoteIdentity ? m_RemoteIdentity->GetIdentHash().ToBase64() : ""; }
2018-01-06 03:48:51 +00:00
std::shared_ptr<const i2p::data::IdentityEx> GetRemoteIdentity ()
2020-04-01 13:54:10 +00:00
{
std::lock_guard<std::mutex> l(m_RemoteIdentityMutex);
return m_RemoteIdentity;
2020-04-01 13:54:10 +00:00
}
void SetRemoteIdentity (std::shared_ptr<const i2p::data::IdentityEx> ident)
2020-04-01 13:54:10 +00:00
{
std::lock_guard<std::mutex> l(m_RemoteIdentityMutex);
m_RemoteIdentity = ident;
2020-04-01 13:54:10 +00:00
}
2018-01-06 03:48:51 +00:00
size_t GetNumSentBytes () const { return m_NumSentBytes; };
2023-10-15 12:31:55 +00:00
void UpdateNumSentBytes (size_t len)
{
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
m_NumSentBytes += len;
UpdateBandwidth ();
}
size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
2023-10-15 12:31:55 +00:00
void UpdateNumReceivedBytes (size_t len)
{
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
m_NumReceivedBytes += len;
UpdateBandwidth ();
}
size_t GetSendQueueSize () const { return m_SendQueueSize; };
2023-10-15 12:31:55 +00:00
void SetSendQueueSize (size_t s) { m_SendQueueSize = s; };
2015-11-03 14:15:49 +00:00
bool IsOutgoing () const { return m_IsOutgoing; };
2023-03-29 19:54:53 +00:00
bool IsSlow () const { return m_HandshakeInterval > TRANSPORT_SESSION_SLOWNESS_THRESHOLD &&
m_HandshakeInterval < TRANSPORT_SESSION_MAX_HANDSHAKE_INTERVAL; };
2023-10-15 12:31:55 +00:00
bool IsBandwidthExceeded (bool isHighBandwidth) const
{
auto limit = isHighBandwidth ? i2p::data::HIGH_BANDWIDTH_LIMIT*1024 : i2p::data::LOW_BANDWIDTH_LIMIT*1024; // convert to bytes
return std::max (m_InBandwidth, m_OutBandwidth) > limit;
}
2023-03-29 19:54:53 +00:00
2016-08-04 14:26:50 +00:00
int GetTerminationTimeout () const { return m_TerminationTimeout; };
2018-01-06 03:48:51 +00:00
void SetTerminationTimeout (int terminationTimeout) { m_TerminationTimeout = terminationTimeout; };
bool IsTerminationTimeoutExpired (uint64_t ts) const
{
return ts >= m_LastActivityTimestamp + GetTerminationTimeout () ||
ts + GetTerminationTimeout () < m_LastActivityTimestamp;
};
2016-08-04 14:26:50 +00:00
uint32_t GetCreationTime () const { return m_CreationTime; };
void SetCreationTime (uint32_t ts) { m_CreationTime = ts; }; // for introducers
2023-10-15 12:31:55 +00:00
uint64_t GetLastActivityTimestamp () const { return m_LastActivityTimestamp; };
void SetLastActivityTimestamp (uint64_t ts) { m_LastActivityTimestamp = ts; };
2022-06-17 22:45:37 +00:00
virtual uint32_t GetRelayTag () const { return 0; };
2022-06-13 18:02:36 +00:00
virtual void SendLocalRouterInfo (bool update = false) { SendI2NPMessages ({ CreateDatabaseStoreMsg () }); };
virtual void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) = 0;
2022-12-11 00:09:37 +00:00
virtual bool IsEstablished () const = 0;
2023-10-15 12:31:55 +00:00
private:
void UpdateBandwidth ()
{
int64_t interval = m_LastActivityTimestamp - m_LastBandwidthUpdateTimestamp;
if (interval < 0 || interval > 60*10) // 10 minutes
{
// clock was adjusted, copy new values
m_LastBandWidthUpdateNumSentBytes = m_NumSentBytes;
m_LastBandWidthUpdateNumReceivedBytes = m_NumReceivedBytes;
m_LastBandwidthUpdateTimestamp = m_LastActivityTimestamp;
return;
}
if ((uint64_t)interval > TRANSPORT_SESSION_BANDWIDTH_UPDATE_MIN_INTERVAL)
2023-10-15 12:31:55 +00:00
{
m_OutBandwidth = (m_NumSentBytes - m_LastBandWidthUpdateNumSentBytes)/interval;
m_LastBandWidthUpdateNumSentBytes = m_NumSentBytes;
m_InBandwidth = (m_NumReceivedBytes - m_LastBandWidthUpdateNumReceivedBytes)/interval;
m_LastBandWidthUpdateNumReceivedBytes = m_NumReceivedBytes;
m_LastBandwidthUpdateTimestamp = m_LastActivityTimestamp;
}
}
2014-10-20 20:09:59 +00:00
protected:
2018-01-06 03:48:51 +00:00
std::shared_ptr<const i2p::data::IdentityEx> m_RemoteIdentity;
2020-04-01 13:54:10 +00:00
mutable std::mutex m_RemoteIdentityMutex;
2015-11-03 14:15:49 +00:00
bool m_IsOutgoing;
2016-08-04 14:26:50 +00:00
int m_TerminationTimeout;
uint32_t m_CreationTime; // seconds since epoch
2023-03-29 19:54:53 +00:00
int64_t m_HandshakeInterval; // in milliseconds between SessionRequest->SessionCreated or SessionCreated->SessionConfirmed
2023-10-15 12:31:55 +00:00
private:
size_t m_SendQueueSize, m_NumSentBytes, m_NumReceivedBytes,
m_LastBandWidthUpdateNumSentBytes, m_LastBandWidthUpdateNumReceivedBytes;
uint64_t m_LastActivityTimestamp, m_LastBandwidthUpdateTimestamp;
uint32_t m_InBandwidth, m_OutBandwidth;
2018-01-06 03:48:51 +00:00
};
2022-10-16 01:37:00 +00:00
// SOCKS5 proxy
const uint8_t SOCKS5_VER = 0x05;
const uint8_t SOCKS5_CMD_CONNECT = 0x01;
const uint8_t SOCKS5_CMD_UDP_ASSOCIATE = 0x03;
const uint8_t SOCKS5_ATYP_IPV4 = 0x01;
const uint8_t SOCKS5_ATYP_IPV6 = 0x04;
2022-10-17 01:23:28 +00:00
const size_t SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE = 10;
const size_t SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE = 22;
2014-10-20 20:09:59 +00:00
}
}
#endif