mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-11 17:37:53 +00:00
split SSU to SSU and SSUData
This commit is contained in:
parent
4bd8195e99
commit
9ec671ba69
2
Makefile
2
Makefile
@ -6,7 +6,7 @@ OBJECTS = obj/i2p.o obj/base64.o obj/NTCPSession.o obj/RouterInfo.o obj/Transpor
|
|||||||
obj/TunnelGateway.o obj/TransitTunnel.o obj/I2NPProtocol.o obj/Log.o obj/Garlic.o \
|
obj/TunnelGateway.o obj/TransitTunnel.o obj/I2NPProtocol.o obj/Log.o obj/Garlic.o \
|
||||||
obj/HTTPServer.o obj/Streaming.o obj/Identity.o obj/SSU.o obj/util.o obj/Reseed.o \
|
obj/HTTPServer.o obj/Streaming.o obj/Identity.o obj/SSU.o obj/util.o obj/Reseed.o \
|
||||||
obj/UPnP.o obj/TunnelPool.o obj/HTTPProxy.o obj/AddressBook.o \
|
obj/UPnP.o obj/TunnelPool.o obj/HTTPProxy.o obj/AddressBook.o \
|
||||||
obj/Daemon.o obj/DaemonLinux.o
|
obj/Daemon.o obj/DaemonLinux.o obj/SSUData.o
|
||||||
INCFLAGS =
|
INCFLAGS =
|
||||||
LDFLAGS = -Wl,-rpath,/usr/local/lib -lcryptopp -lboost_system -lboost_filesystem -lboost_regex -lboost_program_options -lpthread
|
LDFLAGS = -Wl,-rpath,/usr/local/lib -lcryptopp -lboost_system -lboost_filesystem -lboost_regex -lboost_program_options -lpthread
|
||||||
LIBS =
|
LIBS =
|
||||||
|
121
SSU.cpp
121
SSU.cpp
@ -19,20 +19,14 @@ namespace ssu
|
|||||||
const i2p::data::RouterInfo * router, bool peerTest ):
|
const i2p::data::RouterInfo * router, bool peerTest ):
|
||||||
m_Server (server), m_RemoteEndpoint (remoteEndpoint), m_RemoteRouter (router),
|
m_Server (server), m_RemoteEndpoint (remoteEndpoint), m_RemoteRouter (router),
|
||||||
m_Timer (m_Server.GetService ()), m_PeerTest (peerTest), m_State (eSessionStateUnknown),
|
m_Timer (m_Server.GetService ()), m_PeerTest (peerTest), m_State (eSessionStateUnknown),
|
||||||
m_IsSessionKey (false), m_RelayTag (0)
|
m_IsSessionKey (false), m_RelayTag (0), m_Data (*this)
|
||||||
{
|
{
|
||||||
m_DHKeysPair = i2p::transports.GetNextDHKeysPair ();
|
m_DHKeysPair = i2p::transports.GetNextDHKeysPair ();
|
||||||
}
|
}
|
||||||
|
|
||||||
SSUSession::~SSUSession ()
|
SSUSession::~SSUSession ()
|
||||||
{
|
{
|
||||||
delete m_DHKeysPair;
|
delete m_DHKeysPair;
|
||||||
for (auto it: m_IncomleteMessages)
|
|
||||||
if (it.second)
|
|
||||||
{
|
|
||||||
DeleteI2NPMessage (it.second->msg);
|
|
||||||
delete it.second;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSUSession::CreateAESandMacKey (const uint8_t * pubKey, uint8_t * aesKey, uint8_t * macKey)
|
void SSUSession::CreateAESandMacKey (const uint8_t * pubKey, uint8_t * aesKey, uint8_t * macKey)
|
||||||
@ -603,6 +597,7 @@ namespace ssu
|
|||||||
|
|
||||||
void SSUSession::Established ()
|
void SSUSession::Established ()
|
||||||
{
|
{
|
||||||
|
m_State = eSessionStateEstablished;
|
||||||
SendI2NPMessage (CreateDatabaseStoreMsg ());
|
SendI2NPMessage (CreateDatabaseStoreMsg ());
|
||||||
if (!m_DelayedMessages.empty ())
|
if (!m_DelayedMessages.empty ())
|
||||||
{
|
{
|
||||||
@ -671,115 +666,7 @@ namespace ssu
|
|||||||
|
|
||||||
void SSUSession::ProcessData (uint8_t * buf, size_t len)
|
void SSUSession::ProcessData (uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
//uint8_t * start = buf;
|
m_Data.ProcessMessage (buf, len);
|
||||||
uint8_t flag = *buf;
|
|
||||||
buf++;
|
|
||||||
LogPrint ("Process SSU data flags=", (int)flag);
|
|
||||||
if (flag & DATA_FLAG_EXPLICIT_ACKS_INCLUDED)
|
|
||||||
{
|
|
||||||
// explicit ACKs
|
|
||||||
uint8_t numAcks =*buf;
|
|
||||||
buf++;
|
|
||||||
// TODO: process ACKs
|
|
||||||
buf += numAcks*4;
|
|
||||||
}
|
|
||||||
if (flag & DATA_FLAG_ACK_BITFIELDS_INCLUDED)
|
|
||||||
{
|
|
||||||
// explicit ACK bitfields
|
|
||||||
uint8_t numBitfields =*buf;
|
|
||||||
buf++;
|
|
||||||
for (int i = 0; i < numBitfields; i++)
|
|
||||||
{
|
|
||||||
buf += 4; // msgID
|
|
||||||
// TODO: process ACH bitfields
|
|
||||||
while (*buf & 0x80) // not last
|
|
||||||
buf++;
|
|
||||||
buf++; // last byte
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uint8_t numFragments = *buf; // number of fragments
|
|
||||||
buf++;
|
|
||||||
for (int i = 0; i < numFragments; i++)
|
|
||||||
{
|
|
||||||
uint32_t msgID = be32toh (*(uint32_t *)buf); // message ID
|
|
||||||
buf += 4;
|
|
||||||
uint8_t frag[4];
|
|
||||||
frag[0] = 0;
|
|
||||||
memcpy (frag + 1, buf, 3);
|
|
||||||
buf += 3;
|
|
||||||
uint32_t fragmentInfo = be32toh (*(uint32_t *)frag); // fragment info
|
|
||||||
uint16_t fragmentSize = fragmentInfo & 0x1FFF; // bits 0 - 13
|
|
||||||
bool isLast = fragmentInfo & 0x010000; // bit 16
|
|
||||||
uint8_t fragmentNum = fragmentInfo >> 17; // bits 23 - 17
|
|
||||||
LogPrint ("SSU data fragment ", (int)fragmentNum, " of message ", msgID, " size=", (int)fragmentSize, isLast ? " last" : " non-last");
|
|
||||||
I2NPMessage * msg = nullptr;
|
|
||||||
if (fragmentNum > 0) // follow-up fragment
|
|
||||||
{
|
|
||||||
auto it = m_IncomleteMessages.find (msgID);
|
|
||||||
if (it != m_IncomleteMessages.end ())
|
|
||||||
{
|
|
||||||
if (fragmentNum == it->second->nextFragmentNum)
|
|
||||||
{
|
|
||||||
// expected fragment
|
|
||||||
msg = it->second->msg;
|
|
||||||
memcpy (msg->buf + msg->len, buf, fragmentSize);
|
|
||||||
msg->len += fragmentSize;
|
|
||||||
it->second->nextFragmentNum++;
|
|
||||||
}
|
|
||||||
else if (fragmentNum < it->second->nextFragmentNum)
|
|
||||||
// duplicate fragment
|
|
||||||
LogPrint ("Duplicate fragment ", fragmentNum, " of message ", msgID, ". Ignored");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// missing fragment
|
|
||||||
LogPrint ("Missing fragments from ", it->second->nextFragmentNum, " to ", fragmentNum - 1, " of message ", msgID);
|
|
||||||
//TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isLast)
|
|
||||||
{
|
|
||||||
delete it->second;
|
|
||||||
m_IncomleteMessages.erase (it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
// TODO:
|
|
||||||
LogPrint ("Unexpected follow-on fragment ", fragmentNum, " of message ", msgID);
|
|
||||||
}
|
|
||||||
else // first fragment
|
|
||||||
{
|
|
||||||
msg = NewI2NPMessage ();
|
|
||||||
memcpy (msg->GetSSUHeader (), buf, fragmentSize);
|
|
||||||
msg->len += fragmentSize - sizeof (I2NPHeaderShort);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (msg)
|
|
||||||
{
|
|
||||||
if (!fragmentNum && !isLast)
|
|
||||||
m_IncomleteMessages[msgID] = new IncompleteMessage (msg);
|
|
||||||
if (isLast)
|
|
||||||
{
|
|
||||||
SendMsgAck (msgID);
|
|
||||||
msg->FromSSU (msgID);
|
|
||||||
if (m_State == eSessionStateEstablished)
|
|
||||||
i2p::HandleI2NPMessage (msg);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// we expect DeliveryStatus
|
|
||||||
if (msg->GetHeader ()->typeID == eI2NPDeliveryStatus)
|
|
||||||
{
|
|
||||||
LogPrint ("SSU session established");
|
|
||||||
m_State = eSessionStateEstablished;
|
|
||||||
Established ();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LogPrint ("SSU unexpected message ", (int)msg->GetHeader ()->typeID);
|
|
||||||
DeleteI2NPMessage (msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buf += fragmentSize;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
22
SSU.h
22
SSU.h
@ -13,6 +13,7 @@
|
|||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
#include "RouterInfo.h"
|
#include "RouterInfo.h"
|
||||||
#include "I2NPProtocol.h"
|
#include "I2NPProtocol.h"
|
||||||
|
#include "SSUData.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
@ -45,14 +46,6 @@ namespace ssu
|
|||||||
const uint8_t PAYLOAD_TYPE_PEER_TEST = 7;
|
const uint8_t PAYLOAD_TYPE_PEER_TEST = 7;
|
||||||
const uint8_t PAYLOAD_TYPE_SESSION_DESTROYED = 8;
|
const uint8_t PAYLOAD_TYPE_SESSION_DESTROYED = 8;
|
||||||
|
|
||||||
// data flags
|
|
||||||
const uint8_t DATA_FLAG_EXTENDED_DATA_INCLUDED = 0x02;
|
|
||||||
const uint8_t DATA_FLAG_WANT_REPLY = 0x04;
|
|
||||||
const uint8_t DATA_FLAG_REQUEST_PREVIOUS_ACKS = 0x08;
|
|
||||||
const uint8_t DATA_FLAG_EXPLICIT_CONGESTION_NOTIFICATION = 0x10;
|
|
||||||
const uint8_t DATA_FLAG_ACK_BITFIELDS_INCLUDED = 0x40;
|
|
||||||
const uint8_t DATA_FLAG_EXPLICIT_ACKS_INCLUDED = 0x80;
|
|
||||||
|
|
||||||
enum SessionState
|
enum SessionState
|
||||||
{
|
{
|
||||||
eSessionStateUnknown,
|
eSessionStateUnknown,
|
||||||
@ -88,6 +81,8 @@ namespace ssu
|
|||||||
void SendI2NPMessage (I2NPMessage * msg);
|
void SendI2NPMessage (I2NPMessage * msg);
|
||||||
void SendPeerTest (); // Alice
|
void SendPeerTest (); // Alice
|
||||||
|
|
||||||
|
SessionState GetState () const { return m_State; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void CreateAESandMacKey (const uint8_t * pubKey, uint8_t * aesKey, uint8_t * macKey);
|
void CreateAESandMacKey (const uint8_t * pubKey, uint8_t * aesKey, uint8_t * macKey);
|
||||||
@ -125,15 +120,8 @@ namespace ssu
|
|||||||
void HandleTerminationTimer (const boost::system::error_code& ecode);
|
void HandleTerminationTimer (const boost::system::error_code& ecode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
struct IncompleteMessage
|
|
||||||
{
|
|
||||||
I2NPMessage * msg;
|
|
||||||
uint8_t nextFragmentNum;
|
|
||||||
|
|
||||||
IncompleteMessage (I2NPMessage * m): msg (m), nextFragmentNum (1) {};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
friend class SSUData; // TODO: change in later
|
||||||
SSUServer& m_Server;
|
SSUServer& m_Server;
|
||||||
boost::asio::ip::udp::endpoint m_RemoteEndpoint;
|
boost::asio::ip::udp::endpoint m_RemoteEndpoint;
|
||||||
const i2p::data::RouterInfo * m_RemoteRouter;
|
const i2p::data::RouterInfo * m_RemoteRouter;
|
||||||
@ -147,8 +135,8 @@ namespace ssu
|
|||||||
CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption m_Encryption;
|
CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption m_Encryption;
|
||||||
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption m_Decryption;
|
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption m_Decryption;
|
||||||
uint8_t m_SessionKey[32], m_MacKey[32];
|
uint8_t m_SessionKey[32], m_MacKey[32];
|
||||||
std::map<uint32_t, IncompleteMessage *> m_IncomleteMessages;
|
|
||||||
std::list<i2p::I2NPMessage *> m_DelayedMessages;
|
std::list<i2p::I2NPMessage *> m_DelayedMessages;
|
||||||
|
SSUData m_Data;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SSUServer
|
class SSUServer
|
||||||
|
138
SSUData.cpp
Normal file
138
SSUData.cpp
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
#include "Log.h"
|
||||||
|
#include "SSU.h"
|
||||||
|
#include "SSUData.h"
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace ssu
|
||||||
|
{
|
||||||
|
SSUData::SSUData (SSUSession& session):
|
||||||
|
m_Session (session)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SSUData::~SSUData ()
|
||||||
|
{
|
||||||
|
for (auto it: m_IncomleteMessages)
|
||||||
|
if (it.second)
|
||||||
|
{
|
||||||
|
DeleteI2NPMessage (it.second->msg);
|
||||||
|
delete it.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSUData::ProcessMessage (uint8_t * buf, size_t len)
|
||||||
|
{
|
||||||
|
//uint8_t * start = buf;
|
||||||
|
uint8_t flag = *buf;
|
||||||
|
buf++;
|
||||||
|
LogPrint ("Process SSU data flags=", (int)flag);
|
||||||
|
if (flag & DATA_FLAG_EXPLICIT_ACKS_INCLUDED)
|
||||||
|
{
|
||||||
|
// explicit ACKs
|
||||||
|
uint8_t numAcks =*buf;
|
||||||
|
buf++;
|
||||||
|
// TODO: process ACKs
|
||||||
|
buf += numAcks*4;
|
||||||
|
}
|
||||||
|
if (flag & DATA_FLAG_ACK_BITFIELDS_INCLUDED)
|
||||||
|
{
|
||||||
|
// explicit ACK bitfields
|
||||||
|
uint8_t numBitfields =*buf;
|
||||||
|
buf++;
|
||||||
|
for (int i = 0; i < numBitfields; i++)
|
||||||
|
{
|
||||||
|
buf += 4; // msgID
|
||||||
|
// TODO: process ACH bitfields
|
||||||
|
while (*buf & 0x80) // not last
|
||||||
|
buf++;
|
||||||
|
buf++; // last byte
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint8_t numFragments = *buf; // number of fragments
|
||||||
|
buf++;
|
||||||
|
for (int i = 0; i < numFragments; i++)
|
||||||
|
{
|
||||||
|
uint32_t msgID = be32toh (*(uint32_t *)buf); // message ID
|
||||||
|
buf += 4;
|
||||||
|
uint8_t frag[4];
|
||||||
|
frag[0] = 0;
|
||||||
|
memcpy (frag + 1, buf, 3);
|
||||||
|
buf += 3;
|
||||||
|
uint32_t fragmentInfo = be32toh (*(uint32_t *)frag); // fragment info
|
||||||
|
uint16_t fragmentSize = fragmentInfo & 0x1FFF; // bits 0 - 13
|
||||||
|
bool isLast = fragmentInfo & 0x010000; // bit 16
|
||||||
|
uint8_t fragmentNum = fragmentInfo >> 17; // bits 23 - 17
|
||||||
|
LogPrint ("SSU data fragment ", (int)fragmentNum, " of message ", msgID, " size=", (int)fragmentSize, isLast ? " last" : " non-last");
|
||||||
|
I2NPMessage * msg = nullptr;
|
||||||
|
if (fragmentNum > 0) // follow-up fragment
|
||||||
|
{
|
||||||
|
auto it = m_IncomleteMessages.find (msgID);
|
||||||
|
if (it != m_IncomleteMessages.end ())
|
||||||
|
{
|
||||||
|
if (fragmentNum == it->second->nextFragmentNum)
|
||||||
|
{
|
||||||
|
// expected fragment
|
||||||
|
msg = it->second->msg;
|
||||||
|
memcpy (msg->buf + msg->len, buf, fragmentSize);
|
||||||
|
msg->len += fragmentSize;
|
||||||
|
it->second->nextFragmentNum++;
|
||||||
|
}
|
||||||
|
else if (fragmentNum < it->second->nextFragmentNum)
|
||||||
|
// duplicate fragment
|
||||||
|
LogPrint ("Duplicate fragment ", fragmentNum, " of message ", msgID, ". Ignored");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// missing fragment
|
||||||
|
LogPrint ("Missing fragments from ", it->second->nextFragmentNum, " to ", fragmentNum - 1, " of message ", msgID);
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLast)
|
||||||
|
{
|
||||||
|
delete it->second;
|
||||||
|
m_IncomleteMessages.erase (it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
// TODO:
|
||||||
|
LogPrint ("Unexpected follow-on fragment ", fragmentNum, " of message ", msgID);
|
||||||
|
}
|
||||||
|
else // first fragment
|
||||||
|
{
|
||||||
|
msg = NewI2NPMessage ();
|
||||||
|
memcpy (msg->GetSSUHeader (), buf, fragmentSize);
|
||||||
|
msg->len += fragmentSize - sizeof (I2NPHeaderShort);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg)
|
||||||
|
{
|
||||||
|
if (!fragmentNum && !isLast)
|
||||||
|
m_IncomleteMessages[msgID] = new IncompleteMessage (msg);
|
||||||
|
if (isLast)
|
||||||
|
{
|
||||||
|
m_Session.SendMsgAck (msgID);
|
||||||
|
msg->FromSSU (msgID);
|
||||||
|
if (m_Session.GetState () == eSessionStateEstablished)
|
||||||
|
i2p::HandleI2NPMessage (msg);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// we expect DeliveryStatus
|
||||||
|
if (msg->GetHeader ()->typeID == eI2NPDeliveryStatus)
|
||||||
|
{
|
||||||
|
LogPrint ("SSU session established");
|
||||||
|
m_Session.Established ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint ("SSU unexpected message ", (int)msg->GetHeader ()->typeID);
|
||||||
|
DeleteI2NPMessage (msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf += fragmentSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
48
SSUData.h
Normal file
48
SSUData.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#ifndef SSU_DATA_H__
|
||||||
|
#define SSU_DATA_H__
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <map>
|
||||||
|
#include "I2NPProtocol.h"
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace ssu
|
||||||
|
{
|
||||||
|
|
||||||
|
// data flags
|
||||||
|
const uint8_t DATA_FLAG_EXTENDED_DATA_INCLUDED = 0x02;
|
||||||
|
const uint8_t DATA_FLAG_WANT_REPLY = 0x04;
|
||||||
|
const uint8_t DATA_FLAG_REQUEST_PREVIOUS_ACKS = 0x08;
|
||||||
|
const uint8_t DATA_FLAG_EXPLICIT_CONGESTION_NOTIFICATION = 0x10;
|
||||||
|
const uint8_t DATA_FLAG_ACK_BITFIELDS_INCLUDED = 0x40;
|
||||||
|
const uint8_t DATA_FLAG_EXPLICIT_ACKS_INCLUDED = 0x80;
|
||||||
|
|
||||||
|
class SSUSession;
|
||||||
|
class SSUData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
SSUData (SSUSession& session);
|
||||||
|
~SSUData ();
|
||||||
|
|
||||||
|
void ProcessMessage (uint8_t * buf, size_t len);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
struct IncompleteMessage
|
||||||
|
{
|
||||||
|
I2NPMessage * msg;
|
||||||
|
uint8_t nextFragmentNum;
|
||||||
|
|
||||||
|
IncompleteMessage (I2NPMessage * m): msg (m), nextFragmentNum (1) {};
|
||||||
|
};
|
||||||
|
|
||||||
|
SSUSession& m_Session;
|
||||||
|
std::map<uint32_t, IncompleteMessage *> m_IncomleteMessages;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user