forked from PurpleI2P/i2pd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
SSU2.h
171 lines (141 loc) · 5.07 KB
/
SSU2.h
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
/*
* Copyright (c) 2022, 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 SSU2_H__
#define SSU2_H__
#include <memory>
#include <map>
#include <unordered_map>
#include <boost/asio.hpp>
#include "Crypto.h"
#include "RouterInfo.h"
#include "TransportSession.h"
namespace i2p
{
namespace transport
{
const int SSU2_CONNECT_TIMEOUT = 5; // 5 seconds
const int SSU2_TERMINATION_TIMEOUT = 330; // 5.5 minutes
const int SSU2_TERMINATION_CHECK_TIMEOUT = 30; // 30 seconds
const size_t SSU2_SOCKET_RECEIVE_BUFFER_SIZE = 0x1FFFF; // 128K
const size_t SSU2_SOCKET_SEND_BUFFER_SIZE = 0x1FFFF; // 128K
const size_t SSU2_MTU = 1488;
enum SSU2MessageType
{
eSSU2SessionRequest = 0,
eSSU2SessionCreated = 1,
eSSU2SessionConfirmed = 2,
eSSU2Retry = 9
};
enum SSU2BlockType
{
eSSU2BlkDateTime = 0,
eSSU2BlkOptions, // 1
eSSU2BlkRouterInfo, // 2
eSSU2BlkI2NPMessage, // 3
eSSU2BlkFirstFragment, // 4
eSSU2BlkFollowOnFragment, // 5
eSSU2BlkTermination, // 6
eSSU2BlkRelayRequest, // 7
eSSU2BlkRelayResponse, // 8
eSSU2BlkRelayIntro, // 9
eSSU2BlkPeerTest, // 10
eSSU2BlkNextNonce, // 11
eSSU2BlkAck, // 12
eSSU2BlkAddress, // 13
eSSU2BlkIntroKey, // 14
eSSU2BlkRelayTagRequest, // 15
eSSU2BlkRelayTag, // 16
eSSU2BlkNewToken, // 17
eSSU2BlkPathChallenge, // 18
eSSU2BlkPathResponse, // 19
eSSU2BlkFirstPacketNumber, // 20
eSSU2BlkPadding = 254
};
// RouterInfo flags
const uint8_t SSU2_ROUTER_INFO_FLAG_REQUEST_FLOOD = 0x01;
const uint8_t SSU2_ROUTER_INFO_FLAG_GZIP = 0x02;
class SSU2Server;
class SSU2Session: public TransportSession, public std::enable_shared_from_this<SSU2Session>
{
union Header
{
uint64_t ll[2];
uint8_t buf[16];
struct
{
uint64_t connID;
uint32_t packetNum;
uint8_t type;
uint8_t flags[3];
} h;
};
public:
SSU2Session (SSU2Server& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter = nullptr,
std::shared_ptr<const i2p::data::RouterInfo::Address> addr = nullptr, bool peerTest = false);
~SSU2Session ();
void SetRemoteEndpoint (const boost::asio::ip::udp::endpoint& ep) { m_RemoteEndpoint = ep; };
void Connect ();
void Done () override {};
void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) override {};
void ProcessSessionRequest (uint64_t connID, uint8_t * buf, size_t len);
bool ProcessSessionCreated (uint8_t * buf, size_t len);
bool ProcessRetry (uint8_t * buf, size_t len);
private:
void SendSessionRequest (uint64_t token = 0);
void SendSessionCreated (const uint8_t * X);
void SendSessionConfirmed (const uint8_t * Y);
void HandlePayload (const uint8_t * buf, size_t len);
bool ExtractEndpoint (const uint8_t * buf, size_t size, boost::asio::ip::udp::endpoint& ep);
size_t CreateAddressBlock (const boost::asio::ip::udp::endpoint& ep, uint8_t * buf, size_t len);
void CreateNonce (uint64_t seqn, uint8_t * nonce);
private:
SSU2Server& m_Server;
std::shared_ptr<i2p::crypto::X25519Keys> m_EphemeralKeys;
std::unique_ptr<i2p::crypto::NoiseSymmetricState> m_NoiseState;
std::shared_ptr<const i2p::data::RouterInfo::Address> m_Address;
boost::asio::ip::udp::endpoint m_RemoteEndpoint;
uint64_t m_DestConnID, m_SourceConnID;
};
class SSU2Server: private i2p::util::RunnableServiceWithWork
{
struct Packet
{
uint8_t buf[SSU2_MTU];
size_t len;
boost::asio::ip::udp::endpoint from;
};
public:
SSU2Server ();
~SSU2Server () {};
void Start ();
void Stop ();
boost::asio::io_service& GetService () { return GetIOService (); };
void AddSession (uint64_t connID, std::shared_ptr<SSU2Session> session);
void AddPendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep, std::shared_ptr<SSU2Session> session);
void Send (const uint8_t * header, size_t headerLen, const uint8_t * headerX, size_t headerXLen,
const uint8_t * payload, size_t payloadLen, const boost::asio::ip::udp::endpoint& to);
bool CreateSession (std::shared_ptr<const i2p::data::RouterInfo> router,
std::shared_ptr<const i2p::data::RouterInfo::Address> address);
private:
boost::asio::ip::udp::socket& OpenSocket (const boost::asio::ip::udp::endpoint& localEndpoint);
void Receive (boost::asio::ip::udp::socket& socket);
void HandleReceivedFrom (const boost::system::error_code& ecode, size_t bytes_transferred,
Packet * packet, boost::asio::ip::udp::socket& socket);
void ProcessNextPacket (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint);
void ScheduleTermination ();
void HandleTerminationTimer (const boost::system::error_code& ecode);
private:
boost::asio::ip::udp::socket m_Socket, m_SocketV6;
std::unordered_map<uint64_t, std::shared_ptr<SSU2Session> > m_Sessions;
std::map<boost::asio::ip::udp::endpoint, std::shared_ptr<SSU2Session> > m_PendingOutgoingSessions;
i2p::util::MemoryPoolMt<Packet> m_PacketsPool;
boost::asio::deadline_timer m_TerminationTimer;
};
}
}
#endif