File: TransportSession.h

package info (click to toggle)
i2pd 2.58.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,612 kB
  • sloc: cpp: 59,663; makefile: 224; sh: 138
file content (204 lines) | stat: -rw-r--r-- 6,729 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/*
* Copyright (c) 2013-2025, 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
*/

#ifndef TRANSPORT_SESSION_H__
#define TRANSPORT_SESSION_H__

#include <inttypes.h>
#include <string.h>
#include <memory>
#include <vector>
#include <mutex>
#include "Identity.h"
#include "Crypto.h"
#include "RouterInfo.h"
#include "I2NPProtocol.h"
#include "Timestamp.h"

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;

	template<size_t sz>
	class SignedData
	{
		public:

			SignedData (): m_Size(0) {}
			SignedData (const SignedData& other)
			{
				m_Size = other.m_Size;
				memcpy (m_Buf, other.m_Buf, m_Size);
			}

			void Reset ()
			{
				m_Size = 0;
			}

			size_t Insert (const uint8_t * buf, size_t len)
			{
				if (m_Size + len > sz) len = sz - m_Size;
				memcpy (m_Buf + m_Size, buf, len); 
				m_Size += len;
				return len;
			}

			template<typename T>
			void Insert (T t)
			{
				Insert ((const uint8_t *)&t, sizeof (T));
			}

			bool Verify (std::shared_ptr<const i2p::data::IdentityEx> ident, const uint8_t * signature) const
			{
				return ident->Verify (m_Buf, m_Size, signature);
			}

			void Sign (const i2p::data::PrivateKeys& keys, uint8_t * signature) const
			{
				keys.Sign (m_Buf, m_Size, signature);
			}

		private:

			uint8_t m_Buf[sz];
			size_t m_Size;
	};

	const int64_t TRANSPORT_SESSION_SLOWNESS_THRESHOLD = 500; // in milliseconds
	const int64_t TRANSPORT_SESSION_MAX_HANDSHAKE_INTERVAL = 10000; // in milliseconds
	const uint64_t TRANSPORT_SESSION_BANDWIDTH_UPDATE_MIN_INTERVAL = 5; // in seconds
	class TransportSession
	{
		public:

			TransportSession (std::shared_ptr<const i2p::data::RouterInfo> router, int terminationTimeout):
				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)
			{
				if (router)
					m_RemoteIdentity = router->GetRouterIdentity ();
				m_CreationTime = m_LastActivityTimestamp;
			}

			virtual ~TransportSession () {};
			virtual void Done () = 0;

			std::string GetIdentHashBase64() const { return m_RemoteIdentity ? m_RemoteIdentity->GetIdentHash().ToBase64() : ""; }

			std::shared_ptr<const i2p::data::IdentityEx> GetRemoteIdentity ()
			{
				std::lock_guard<std::mutex> l(m_RemoteIdentityMutex);
				return m_RemoteIdentity;
			}
			void SetRemoteIdentity (std::shared_ptr<const i2p::data::IdentityEx> ident)
			{
				std::lock_guard<std::mutex> l(m_RemoteIdentityMutex);
				m_RemoteIdentity = ident;
			}

			size_t GetNumSentBytes () const { return m_NumSentBytes; };
			void UpdateNumSentBytes (size_t len)
			{
				m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
				m_NumSentBytes += len;
				UpdateBandwidth ();
			}	
			size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
			void UpdateNumReceivedBytes (size_t len)
			{
				m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
				m_NumReceivedBytes += len;
				UpdateBandwidth ();
			}		
			size_t GetSendQueueSize () const { return m_SendQueueSize; };
			void SetSendQueueSize (size_t s) { m_SendQueueSize = s; };
			bool IsOutgoing () const { return m_IsOutgoing; };
			bool IsSlow () const { return m_HandshakeInterval > TRANSPORT_SESSION_SLOWNESS_THRESHOLD &&
				m_HandshakeInterval < TRANSPORT_SESSION_MAX_HANDSHAKE_INTERVAL; };
			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;
			}	
			
			int GetTerminationTimeout () const { return m_TerminationTimeout; };
			void SetTerminationTimeout (int terminationTimeout) { m_TerminationTimeout = terminationTimeout; };
			bool IsTerminationTimeoutExpired (uint64_t ts) const
			{
				return ts >= m_LastActivityTimestamp + GetTerminationTimeout () ||
					ts + GetTerminationTimeout () < m_LastActivityTimestamp;
			};

			uint32_t GetCreationTime () const { return m_CreationTime; };
			void SetCreationTime (uint32_t ts) { m_CreationTime = ts; }; // for introducers

			uint64_t GetLastActivityTimestamp () const { return m_LastActivityTimestamp; };
			void SetLastActivityTimestamp (uint64_t ts) { m_LastActivityTimestamp = ts; };
			
			virtual uint32_t GetRelayTag () const { return 0; };
			virtual void SendLocalRouterInfo (bool update = false) 
			{
				std::list<std::shared_ptr<I2NPMessage> > msgs{ CreateDatabaseStoreMsg () };
				SendI2NPMessages (msgs); 
			};
			virtual void SendI2NPMessages (std::list<std::shared_ptr<I2NPMessage> >& msgs) = 0;
			virtual bool IsEstablished () const = 0;
			virtual i2p::data::RouterInfo::SupportedTransports GetTransportType () const = 0;

		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)
				{	
					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;
				}	
			}	
			
		protected:

			std::shared_ptr<const i2p::data::IdentityEx> m_RemoteIdentity;
			mutable std::mutex m_RemoteIdentityMutex;
			bool m_IsOutgoing;
			int m_TerminationTimeout;
			uint32_t m_CreationTime; // seconds since epoch
			int64_t m_HandshakeInterval; // in milliseconds between SessionRequest->SessionCreated or SessionCreated->SessionConfirmed

		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;
	};
}
}

#endif