mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-23 05:47:17 +01:00
Merge branch 'master' of github-meeh420:orignal/i2pd
* 'master' of github-meeh420:orignal/i2pd: delete unreachable SSU sessions show number sent/received bytes through the status page resend fixed memory leak close connection to first hop of declined tunnel process extended data handle individaul bitfields ack Moving file list to a common one. Still in makefile format, but now with CPP/H as input instead of OBJECTS. Issue #82 Removing Qt build file. Issue #82 create inbound tunnel though outbound Makefile now detects which file to use (OSX or Linux) Issue #82 Prepare support for POST/PUT close SSU session if not established send ack per fragment. temporary disble check for duplicated through IV fixed memory leak save out-of-sequence fragments
This commit is contained in:
commit
45289891d6
|
@ -303,6 +303,7 @@ namespace util
|
||||||
s << it.second->GetRemoteRouterInfo ().GetIdentHashAbbreviation () << ": "
|
s << it.second->GetRemoteRouterInfo ().GetIdentHashAbbreviation () << ": "
|
||||||
<< it.second->GetSocket ().remote_endpoint().address ().to_string ();
|
<< it.second->GetSocket ().remote_endpoint().address ().to_string ();
|
||||||
if (!outgoing) s << "-->";
|
if (!outgoing) s << "-->";
|
||||||
|
s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
|
||||||
s << "<BR>";
|
s << "<BR>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -318,13 +319,18 @@ namespace util
|
||||||
if (outgoing) s << "-->";
|
if (outgoing) s << "-->";
|
||||||
s << endpoint.address ().to_string () << ":" << endpoint.port ();
|
s << endpoint.address ().to_string () << ":" << endpoint.port ();
|
||||||
if (!outgoing) s << "-->";
|
if (!outgoing) s << "-->";
|
||||||
|
s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
|
||||||
s << "<BR>";
|
s << "<BR>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s << "<p><a href=\"zmw2cyw2vj7f6obx3msmdvdepdhnw2ctc4okza2zjxlukkdfckhq\">Flibusta</a></p>";
|
s << "<p><a href=\"zmw2cyw2vj7f6obx3msmdvdepdhnw2ctc4okza2zjxlukkdfckhq\">Flibusta</a></p>";
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTPConnection::HandleDestinationRequest (const std::string& address, const std::string& uri)
|
void HTTPConnection::HandleDestinationRequest (const std::string& address, const std::string& uri)
|
||||||
|
{
|
||||||
|
HandleDestinationRequest(address, "GET", "", uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTTPConnection::HandleDestinationRequest (const std::string& address, const std::string& method, const std::string& data, const std::string& uri)
|
||||||
{
|
{
|
||||||
i2p::data::IdentHash destination;
|
i2p::data::IdentHash destination;
|
||||||
std::string fullAddress;
|
std::string fullAddress;
|
||||||
|
@ -380,7 +386,13 @@ namespace util
|
||||||
m_Stream = i2p::stream::CreateStream (*leaseSet);
|
m_Stream = i2p::stream::CreateStream (*leaseSet);
|
||||||
if (m_Stream)
|
if (m_Stream)
|
||||||
{
|
{
|
||||||
std::string request = "GET " + uri + " HTTP/1.1\n Host:" + fullAddress + "\n";
|
std::string request = method+" " + uri + " HTTP/1.1\n Host:" + fullAddress + "\r\n";
|
||||||
|
if (!strcmp(method.c_str(), "GET"))
|
||||||
|
{
|
||||||
|
// POST/PUT, apply body
|
||||||
|
request += "\r\n"+ data;
|
||||||
|
}
|
||||||
|
LogPrint("HTTP Client Request: ", request);
|
||||||
m_Stream->Send ((uint8_t *)request.c_str (), request.length (), 10);
|
m_Stream->Send ((uint8_t *)request.c_str (), request.length (), 10);
|
||||||
AsyncStreamReceive ();
|
AsyncStreamReceive ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,9 @@ namespace util
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
||||||
virtual void HandleDestinationRequest(const std::string& address, const std::string& uri);
|
virtual void HandleDestinationRequest(const std::string& address, const std::string& uri);
|
||||||
|
virtual void HandleDestinationRequest(const std::string& address, const std::string& method, const std::string& data, const std::string& uri);
|
||||||
virtual void RunRequest ();
|
virtual void RunRequest ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -359,6 +359,7 @@ namespace i2p
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint ("Outbound tunnel ", tunnel->GetTunnelID (), " has been declined");
|
LogPrint ("Outbound tunnel ", tunnel->GetTunnelID (), " has been declined");
|
||||||
|
i2p::transports.CloseSession (tunnel->GetTunnelConfig ()->GetFirstHop ()->router);
|
||||||
delete tunnel;
|
delete tunnel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
39
Makefile
39
Makefile
|
@ -1,38 +1,9 @@
|
||||||
|
|
||||||
CC = g++
|
UNAME := $(shell uname -s)
|
||||||
CFLAGS = -g -Wall -std=c++0x
|
|
||||||
OBJECTS = obj/CryptoConst.o obj/base64.o obj/NTCPSession.o obj/RouterInfo.o obj/Transports.o \
|
|
||||||
obj/RouterContext.o obj/NetDb.o obj/LeaseSet.o obj/Tunnel.o obj/TunnelEndpoint.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/UPnP.o obj/TunnelPool.o obj/HTTPProxy.o obj/AddressBook.o obj/Daemon.o \
|
|
||||||
obj/DaemonLinux.o obj/SSUData.o obj/i2p.o obj/aes.o obj/SOCKS.o
|
|
||||||
INCFLAGS =
|
|
||||||
LDFLAGS = -Wl,-rpath,/usr/local/lib -lcryptopp -lboost_system -lboost_filesystem -lboost_regex -lboost_program_options -lpthread
|
|
||||||
LIBS =
|
|
||||||
|
|
||||||
#check if AES-NI is supported by CPU
|
ifeq ($(UNAME),Darwin)
|
||||||
ifneq ($(shell grep -c aes /proc/cpuinfo),0)
|
include Makefile.osx
|
||||||
CPU_FLAGS = -DAESNI
|
else
|
||||||
|
include Makefile.linux
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all: obj i2p
|
|
||||||
|
|
||||||
i2p: $(OBJECTS:obj/%=obj/%)
|
|
||||||
$(CC) -o $@ $^ $(LDFLAGS) $(LIBS)
|
|
||||||
|
|
||||||
.SUFFIXES:
|
|
||||||
.SUFFIXES: .c .cc .C .cpp .o
|
|
||||||
|
|
||||||
obj/%.o : %.cpp
|
|
||||||
$(CC) -o $@ $< -c $(CFLAGS) $(INCFLAGS) $(CPU_FLAGS)
|
|
||||||
|
|
||||||
obj:
|
|
||||||
mkdir -p obj
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -fr obj i2p
|
|
||||||
|
|
||||||
.PHONY: all
|
|
||||||
.PHONY: clean
|
|
||||||
|
|
||||||
|
|
33
Makefile.linux
Normal file
33
Makefile.linux
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
|
||||||
|
CC = g++
|
||||||
|
CFLAGS = -g -Wall -std=c++0x
|
||||||
|
include filelist.mk
|
||||||
|
INCFLAGS =
|
||||||
|
LDFLAGS = -Wl,-rpath,/usr/local/lib -lcryptopp -lboost_system -lboost_filesystem -lboost_regex -lboost_program_options -lpthread
|
||||||
|
LIBS =
|
||||||
|
|
||||||
|
#check if AES-NI is supported by CPU
|
||||||
|
ifneq ($(shell grep -c aes /proc/cpuinfo),0)
|
||||||
|
CPU_FLAGS = -DAESNI
|
||||||
|
endif
|
||||||
|
|
||||||
|
all: obj i2p
|
||||||
|
|
||||||
|
i2p: $(OBJECTS:obj/%=obj/%)
|
||||||
|
$(CC) -o $@ $^ $(LDFLAGS) $(LIBS)
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
.SUFFIXES: .c .cc .C .cpp .o
|
||||||
|
|
||||||
|
obj/%.o : %.cpp
|
||||||
|
$(CC) -o $@ $< -c $(CFLAGS) $(INCFLAGS) $(CPU_FLAGS)
|
||||||
|
|
||||||
|
obj:
|
||||||
|
mkdir -p obj
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -fr obj i2p
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
.PHONY: clean
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
CC = clang++
|
CC = clang++
|
||||||
CFLAGS = -g -Wall -std=c++11 -lstdc++ -I/usr/local/include
|
CFLAGS = -g -Wall -std=c++11 -lstdc++ -I/usr/local/include
|
||||||
OBJECTS = obj/CryptoConst.o obj/base64.o obj/NTCPSession.o obj/RouterInfo.o obj/Transports.o \
|
include filelist.mk
|
||||||
obj/RouterContext.o obj/NetDb.o obj/LeaseSet.o obj/Tunnel.o obj/TunnelEndpoint.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/UPnP.o obj/TunnelPool.o obj/HTTPProxy.o obj/AddressBook.o obj/Daemon.o \
|
|
||||||
obj/DaemonLinux.o obj/SSUData.o obj/i2p.o obj/aes.o obj/SOCKS.o
|
|
||||||
INCFLAGS = -DCRYPTOPP_DISABLE_ASM
|
INCFLAGS = -DCRYPTOPP_DISABLE_ASM
|
||||||
LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib -lcryptopp -lboost_system -lboost_filesystem -lboost_regex -lboost_program_options -lpthread
|
LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib -lcryptopp -lboost_system -lboost_filesystem -lboost_regex -lboost_program_options -lpthread
|
||||||
LIBS =
|
LIBS =
|
||||||
|
|
|
@ -21,7 +21,8 @@ namespace ntcp
|
||||||
{
|
{
|
||||||
NTCPSession::NTCPSession (boost::asio::io_service& service, i2p::data::RouterInfo& in_RemoteRouterInfo):
|
NTCPSession::NTCPSession (boost::asio::io_service& service, i2p::data::RouterInfo& in_RemoteRouterInfo):
|
||||||
m_Socket (service), m_TerminationTimer (service), m_IsEstablished (false),
|
m_Socket (service), m_TerminationTimer (service), m_IsEstablished (false),
|
||||||
m_RemoteRouterInfo (in_RemoteRouterInfo), m_ReceiveBufferOffset (0), m_NextMessage (nullptr)
|
m_RemoteRouterInfo (in_RemoteRouterInfo), m_ReceiveBufferOffset (0), m_NextMessage (nullptr),
|
||||||
|
m_NumSentBytes (0), m_NumReceivedBytes (0)
|
||||||
{
|
{
|
||||||
m_DHKeysPair = i2p::transports.GetNextDHKeysPair ();
|
m_DHKeysPair = i2p::transports.GetNextDHKeysPair ();
|
||||||
}
|
}
|
||||||
|
@ -29,7 +30,6 @@ namespace ntcp
|
||||||
NTCPSession::~NTCPSession ()
|
NTCPSession::~NTCPSession ()
|
||||||
{
|
{
|
||||||
delete m_DHKeysPair;
|
delete m_DHKeysPair;
|
||||||
delete m_NextMessage;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTCPSession::CreateAESKey (uint8_t * pubKey, uint8_t * aesKey)
|
void NTCPSession::CreateAESKey (uint8_t * pubKey, uint8_t * aesKey)
|
||||||
|
@ -403,7 +403,7 @@ namespace ntcp
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint ("Received: ", bytes_transferred);
|
m_NumReceivedBytes += bytes_transferred;
|
||||||
m_ReceiveBufferOffset += bytes_transferred;
|
m_ReceiveBufferOffset += bytes_transferred;
|
||||||
|
|
||||||
if (m_ReceiveBufferOffset >= 16)
|
if (m_ReceiveBufferOffset >= 16)
|
||||||
|
@ -514,7 +514,7 @@ namespace ntcp
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint ("Msg sent: ", bytes_transferred);
|
m_NumSentBytes += bytes_transferred;
|
||||||
ScheduleTermination (); // reset termination timer
|
ScheduleTermination (); // reset termination timer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,6 +79,9 @@ namespace ntcp
|
||||||
void ServerLogin ();
|
void ServerLogin ();
|
||||||
void SendI2NPMessage (I2NPMessage * msg);
|
void SendI2NPMessage (I2NPMessage * msg);
|
||||||
|
|
||||||
|
size_t GetNumSentBytes () const { return m_NumSentBytes; };
|
||||||
|
size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void Terminate ();
|
void Terminate ();
|
||||||
|
@ -142,6 +145,8 @@ namespace ntcp
|
||||||
i2p::I2NPMessage * m_NextMessage;
|
i2p::I2NPMessage * m_NextMessage;
|
||||||
std::list<i2p::I2NPMessage *> m_DelayedMessages;
|
std::list<i2p::I2NPMessage *> m_DelayedMessages;
|
||||||
size_t m_NextMessageOffset;
|
size_t m_NextMessageOffset;
|
||||||
|
|
||||||
|
size_t m_NumSentBytes, m_NumReceivedBytes;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NTCPClient: public NTCPSession
|
class NTCPClient: public NTCPSession
|
||||||
|
|
19
SSU.cpp
19
SSU.cpp
|
@ -19,7 +19,8 @@ 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_Data (*this)
|
m_IsSessionKey (false), m_RelayTag (0), m_Data (*this),
|
||||||
|
m_NumSentBytes (0), m_NumReceivedBytes (0)
|
||||||
{
|
{
|
||||||
m_DHKeysPair = i2p::transports.GetNextDHKeysPair ();
|
m_DHKeysPair = i2p::transports.GetNextDHKeysPair ();
|
||||||
}
|
}
|
||||||
|
@ -74,6 +75,7 @@ namespace ssu
|
||||||
|
|
||||||
void SSUSession::ProcessNextMessage (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint)
|
void SSUSession::ProcessNextMessage (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint)
|
||||||
{
|
{
|
||||||
|
m_NumReceivedBytes += len;
|
||||||
if (m_State == eSessionStateIntroduced)
|
if (m_State == eSessionStateIntroduced)
|
||||||
{
|
{
|
||||||
// HolePunch received
|
// HolePunch received
|
||||||
|
@ -83,11 +85,12 @@ namespace ssu
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (m_State == eSessionStateEstablished)
|
||||||
ScheduleTermination ();
|
ScheduleTermination ();
|
||||||
// check for duplicate
|
/* // check for duplicate
|
||||||
const uint8_t * iv = ((SSUHeader *)buf)->iv;
|
const uint8_t * iv = ((SSUHeader *)buf)->iv;
|
||||||
if (m_ReceivedIVs.count (iv)) return; // duplicate detected
|
if (m_ReceivedIVs.count (iv)) return; // duplicate detected
|
||||||
m_ReceivedIVs.insert (iv);
|
m_ReceivedIVs.insert (iv);*/
|
||||||
|
|
||||||
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);
|
||||||
|
@ -652,7 +655,6 @@ namespace ssu
|
||||||
if (m_State != eSessionStateFailed)
|
if (m_State != eSessionStateFailed)
|
||||||
{
|
{
|
||||||
m_State = eSessionStateFailed;
|
m_State = eSessionStateFailed;
|
||||||
Close ();
|
|
||||||
m_Server.DeleteSession (this); // delete this
|
m_Server.DeleteSession (this); // delete this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -822,6 +824,7 @@ namespace ssu
|
||||||
// encrypt message with session key
|
// encrypt message with session key
|
||||||
FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_DESTROYED, buf, 48);
|
FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_DESTROYED, buf, 48);
|
||||||
Send (buf, 48);
|
Send (buf, 48);
|
||||||
|
LogPrint ("SSU session destoryed sent");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -842,6 +845,7 @@ namespace ssu
|
||||||
|
|
||||||
void SSUSession::Send (const uint8_t * buf, size_t size)
|
void SSUSession::Send (const uint8_t * buf, size_t size)
|
||||||
{
|
{
|
||||||
|
m_NumSentBytes += size;
|
||||||
m_Server.Send (buf, size, m_RemoteEndpoint);
|
m_Server.Send (buf, size, m_RemoteEndpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -910,7 +914,6 @@ namespace ssu
|
||||||
void SSUServer::Send (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& to)
|
void SSUServer::Send (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& to)
|
||||||
{
|
{
|
||||||
m_Socket.send_to (boost::asio::buffer (buf, len), to);
|
m_Socket.send_to (boost::asio::buffer (buf, len), to);
|
||||||
LogPrint ("SSU sent ", len, " bytes");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSUServer::Receive ()
|
void SSUServer::Receive ()
|
||||||
|
@ -923,7 +926,6 @@ namespace ssu
|
||||||
{
|
{
|
||||||
if (!ecode)
|
if (!ecode)
|
||||||
{
|
{
|
||||||
LogPrint ("SSU received ", bytes_transferred, " bytes");
|
|
||||||
SSUSession * session = nullptr;
|
SSUSession * session = nullptr;
|
||||||
auto it = m_Sessions.find (m_SenderEndpoint);
|
auto it = m_Sessions.find (m_SenderEndpoint);
|
||||||
if (it != m_Sessions.end ())
|
if (it != m_Sessions.end ())
|
||||||
|
@ -1020,7 +1022,12 @@ namespace ssu
|
||||||
introducerSession->Introduce (introducer->iTag, introducer->iKey);
|
introducerSession->Introduce (introducer->iTag, introducer->iKey);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
LogPrint ("Router is unreachable, but no introducers presented. Ignored");
|
LogPrint ("Router is unreachable, but no introducers presented. Ignored");
|
||||||
|
m_Sessions.erase (remoteEndpoint);
|
||||||
|
delete session;
|
||||||
|
session = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
5
SSU.h
5
SSU.h
|
@ -31,7 +31,6 @@ namespace ssu
|
||||||
};
|
};
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
const size_t SSU_MTU = 1484;
|
|
||||||
const int SSU_CONNECT_TIMEOUT = 5; // 5 seconds
|
const int SSU_CONNECT_TIMEOUT = 5; // 5 seconds
|
||||||
const int SSU_TERMINATION_TIMEOUT = 330; // 5.5 minutes
|
const int SSU_TERMINATION_TIMEOUT = 330; // 5.5 minutes
|
||||||
|
|
||||||
|
@ -74,6 +73,9 @@ namespace ssu
|
||||||
void SendPeerTest (); // Alice
|
void SendPeerTest (); // Alice
|
||||||
|
|
||||||
SessionState GetState () const { return m_State; };
|
SessionState GetState () const { return m_State; };
|
||||||
|
size_t GetNumSentBytes () const { return m_NumSentBytes; };
|
||||||
|
size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -132,6 +134,7 @@ namespace ssu
|
||||||
std::list<i2p::I2NPMessage *> m_DelayedMessages;
|
std::list<i2p::I2NPMessage *> m_DelayedMessages;
|
||||||
std::set<IV> m_ReceivedIVs;
|
std::set<IV> m_ReceivedIVs;
|
||||||
SSUData m_Data;
|
SSUData m_Data;
|
||||||
|
size_t m_NumSentBytes, m_NumReceivedBytes;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SSUServer
|
class SSUServer
|
||||||
|
|
256
SSUData.cpp
256
SSUData.cpp
|
@ -1,4 +1,7 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <boost/bind.hpp>
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "Timestamp.h"
|
||||||
#include "SSU.h"
|
#include "SSU.h"
|
||||||
#include "SSUData.h"
|
#include "SSUData.h"
|
||||||
|
|
||||||
|
@ -7,7 +10,7 @@ namespace i2p
|
||||||
namespace ssu
|
namespace ssu
|
||||||
{
|
{
|
||||||
SSUData::SSUData (SSUSession& session):
|
SSUData::SSUData (SSUSession& session):
|
||||||
m_Session (session)
|
m_Session (session), m_ResendTimer (session.m_Server.GetService ())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,10 +23,7 @@ namespace ssu
|
||||||
delete it.second;
|
delete it.second;
|
||||||
}
|
}
|
||||||
for (auto it: m_SentMessages)
|
for (auto it: m_SentMessages)
|
||||||
{
|
delete it.second;
|
||||||
for (auto f: it.second)
|
|
||||||
delete[] f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSUData::ProcessSentMessageAck (uint32_t msgID)
|
void SSUData::ProcessSentMessageAck (uint32_t msgID)
|
||||||
|
@ -31,19 +31,15 @@ namespace ssu
|
||||||
auto it = m_SentMessages.find (msgID);
|
auto it = m_SentMessages.find (msgID);
|
||||||
if (it != m_SentMessages.end ())
|
if (it != m_SentMessages.end ())
|
||||||
{
|
{
|
||||||
// delete all ack-ed message's fragments
|
delete it->second;
|
||||||
for (auto f: it->second)
|
|
||||||
delete[] f;
|
|
||||||
m_SentMessages.erase (it);
|
m_SentMessages.erase (it);
|
||||||
|
if (m_SentMessages.empty ())
|
||||||
|
m_ResendTimer.cancel ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSUData::ProcessMessage (uint8_t * buf, size_t len)
|
void SSUData::ProcessAcks (uint8_t *& buf, uint8_t flag)
|
||||||
{
|
{
|
||||||
//uint8_t * start = buf;
|
|
||||||
uint8_t flag = *buf;
|
|
||||||
buf++;
|
|
||||||
LogPrint ("Process SSU data flags=", (int)flag);
|
|
||||||
if (flag & DATA_FLAG_EXPLICIT_ACKS_INCLUDED)
|
if (flag & DATA_FLAG_EXPLICIT_ACKS_INCLUDED)
|
||||||
{
|
{
|
||||||
// explicit ACKs
|
// explicit ACKs
|
||||||
|
@ -60,13 +56,45 @@ namespace ssu
|
||||||
buf++;
|
buf++;
|
||||||
for (int i = 0; i < numBitfields; i++)
|
for (int i = 0; i < numBitfields; i++)
|
||||||
{
|
{
|
||||||
|
uint32_t msgID = be32toh (*(uint32_t *)buf);
|
||||||
buf += 4; // msgID
|
buf += 4; // msgID
|
||||||
// TODO: process individual Ack bitfields
|
auto it = m_SentMessages.find (msgID);
|
||||||
while (*buf & 0x80) // not last
|
// process individual Ack bitfields
|
||||||
|
bool isNonLast = false;
|
||||||
|
int fragment = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
uint8_t bitfield = *buf;
|
||||||
|
isNonLast = bitfield & 0x80;
|
||||||
|
bitfield &= 0x7F; // clear MSB
|
||||||
|
if (bitfield && it != m_SentMessages.end ())
|
||||||
|
{
|
||||||
|
int numSentFragments = it->second->fragments.size ();
|
||||||
|
// process bits
|
||||||
|
uint8_t mask = 0x40;
|
||||||
|
for (int j = 0; j < 7; j++)
|
||||||
|
{
|
||||||
|
if (bitfield & mask)
|
||||||
|
{
|
||||||
|
if (fragment < numSentFragments)
|
||||||
|
{
|
||||||
|
delete it->second->fragments[fragment];
|
||||||
|
it->second->fragments[fragment] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fragment++;
|
||||||
|
mask >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
buf++;
|
buf++;
|
||||||
buf++; // last byte
|
}
|
||||||
|
while (isNonLast);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSUData::ProcessFragments (uint8_t * buf)
|
||||||
|
{
|
||||||
uint8_t numFragments = *buf; // number of fragments
|
uint8_t numFragments = *buf; // number of fragments
|
||||||
buf++;
|
buf++;
|
||||||
for (int i = 0; i < numFragments; i++)
|
for (int i = 0; i < numFragments; i++)
|
||||||
|
@ -82,55 +110,80 @@ namespace ssu
|
||||||
bool isLast = fragmentInfo & 0x010000; // bit 16
|
bool isLast = fragmentInfo & 0x010000; // bit 16
|
||||||
uint8_t fragmentNum = fragmentInfo >> 17; // bits 23 - 17
|
uint8_t fragmentNum = fragmentInfo >> 17; // bits 23 - 17
|
||||||
LogPrint ("SSU data fragment ", (int)fragmentNum, " of message ", msgID, " size=", (int)fragmentSize, isLast ? " last" : " non-last");
|
LogPrint ("SSU data fragment ", (int)fragmentNum, " of message ", msgID, " size=", (int)fragmentSize, isLast ? " last" : " non-last");
|
||||||
|
|
||||||
|
// find message with msgID
|
||||||
I2NPMessage * msg = nullptr;
|
I2NPMessage * msg = nullptr;
|
||||||
if (fragmentNum > 0) // follow-up fragment
|
IncompleteMessage * incompleteMessage = nullptr;
|
||||||
{
|
|
||||||
auto it = m_IncomleteMessages.find (msgID);
|
auto it = m_IncomleteMessages.find (msgID);
|
||||||
if (it != m_IncomleteMessages.end ())
|
if (it != m_IncomleteMessages.end ())
|
||||||
{
|
{
|
||||||
if (fragmentNum == it->second->nextFragmentNum)
|
// message exists
|
||||||
|
incompleteMessage = it->second;
|
||||||
|
msg = incompleteMessage->msg;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// create new message
|
||||||
|
msg = NewI2NPMessage ();
|
||||||
|
msg->len -= sizeof (I2NPHeaderShort);
|
||||||
|
incompleteMessage = new IncompleteMessage (msg);
|
||||||
|
m_IncomleteMessages[msgID] = incompleteMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle current fragment
|
||||||
|
if (fragmentNum == incompleteMessage->nextFragmentNum)
|
||||||
{
|
{
|
||||||
// expected fragment
|
// expected fragment
|
||||||
msg = it->second->msg;
|
|
||||||
memcpy (msg->buf + msg->len, buf, fragmentSize);
|
memcpy (msg->buf + msg->len, buf, fragmentSize);
|
||||||
msg->len += fragmentSize;
|
msg->len += fragmentSize;
|
||||||
it->second->nextFragmentNum++;
|
incompleteMessage->nextFragmentNum++;
|
||||||
|
if (!isLast && !incompleteMessage->savedFragments.empty ())
|
||||||
|
{
|
||||||
|
// try saved fragments
|
||||||
|
for (auto it1 = incompleteMessage->savedFragments.begin (); it1 != incompleteMessage->savedFragments.end ();)
|
||||||
|
{
|
||||||
|
auto savedFragment = *it1;
|
||||||
|
if (savedFragment->fragmentNum == incompleteMessage->nextFragmentNum)
|
||||||
|
{
|
||||||
|
memcpy (msg->buf + msg->len, savedFragment->buf, savedFragment->len);
|
||||||
|
msg->len += savedFragment->len;
|
||||||
|
isLast = savedFragment->isLast;
|
||||||
|
incompleteMessage->nextFragmentNum++;
|
||||||
|
incompleteMessage->savedFragments.erase (it1++);
|
||||||
|
delete savedFragment;
|
||||||
}
|
}
|
||||||
else if (fragmentNum < it->second->nextFragmentNum)
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (isLast)
|
||||||
|
LogPrint ("Message ", msgID, " complete");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (fragmentNum < incompleteMessage->nextFragmentNum)
|
||||||
// duplicate fragment
|
// duplicate fragment
|
||||||
LogPrint ("Duplicate fragment ", (int)fragmentNum, " of message ", msgID, ". Ignored");
|
LogPrint ("Duplicate fragment ", (int)fragmentNum, " of message ", msgID, ". Ignored");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// missing fragment
|
// missing fragment
|
||||||
LogPrint ("Missing fragments from ", it->second->nextFragmentNum, " to ", fragmentNum - 1, " of message ", msgID);
|
LogPrint ("Missing fragments from ", (int)incompleteMessage->nextFragmentNum, " to ", fragmentNum - 1, " of message ", msgID);
|
||||||
//TODO
|
auto savedFragment = new Fragment (fragmentNum, buf, fragmentSize, isLast);
|
||||||
|
if (!incompleteMessage->savedFragments.insert (savedFragment).second)
|
||||||
|
{
|
||||||
|
LogPrint ("Fragment ", (int)fragmentNum, " of message ", msgID, " already saved");
|
||||||
|
delete savedFragment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isLast = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLast)
|
if (isLast)
|
||||||
{
|
{
|
||||||
if (!msg)
|
// delete incomplete message
|
||||||
DeleteI2NPMessage (it->second->msg);
|
delete incompleteMessage;
|
||||||
delete it->second;
|
m_IncomleteMessages.erase (msgID);
|
||||||
m_IncomleteMessages.erase (it);
|
// process message
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
// TODO:
|
|
||||||
LogPrint ("Unexpected follow-on fragment ", (int)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);
|
SendMsgAck (msgID);
|
||||||
msg->FromSSU (msgID);
|
msg->FromSSU (msgID);
|
||||||
if (m_Session.GetState () == eSessionStateEstablished)
|
if (m_Session.GetState () == eSessionStateEstablished)
|
||||||
|
@ -148,11 +201,33 @@ namespace ssu
|
||||||
DeleteI2NPMessage (msg);
|
DeleteI2NPMessage (msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
SendFragmentAck (msgID, fragmentNum);
|
||||||
buf += fragmentSize;
|
buf += fragmentSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
// process acks if presented
|
||||||
|
if (flag & (DATA_FLAG_ACK_BITFIELDS_INCLUDED | DATA_FLAG_EXPLICIT_ACKS_INCLUDED))
|
||||||
|
ProcessAcks (buf, flag);
|
||||||
|
// extended data if presented
|
||||||
|
if (flag & DATA_FLAG_EXTENDED_DATA_INCLUDED)
|
||||||
|
{
|
||||||
|
uint8_t extendedDataSize = *buf;
|
||||||
|
buf++; // size
|
||||||
|
LogPrint ("SSU extended data of ", extendedDataSize, " bytes presented");
|
||||||
|
buf += extendedDataSize;
|
||||||
|
}
|
||||||
|
// process data
|
||||||
|
ProcessFragments (buf);
|
||||||
|
}
|
||||||
|
|
||||||
void SSUData::Send (i2p::I2NPMessage * msg)
|
void SSUData::Send (i2p::I2NPMessage * msg)
|
||||||
{
|
{
|
||||||
uint32_t msgID = msg->ToSSU ();
|
uint32_t msgID = msg->ToSSU ();
|
||||||
|
@ -162,7 +237,13 @@ namespace ssu
|
||||||
DeleteI2NPMessage (msg);
|
DeleteI2NPMessage (msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto fragments = m_SentMessages[msgID];
|
if (m_SentMessages.empty ()) // schedule resend at first message only
|
||||||
|
ScheduleResend ();
|
||||||
|
SentMessage * sentMessage = new SentMessage;
|
||||||
|
m_SentMessages[msgID] = sentMessage;
|
||||||
|
sentMessage->nextResendTime = i2p::util::GetSecondsSinceEpoch () + RESEND_INTERVAL;
|
||||||
|
sentMessage->numResends = 0;
|
||||||
|
auto& fragments = sentMessage->fragments;
|
||||||
msgID = htobe32 (msgID);
|
msgID = htobe32 (msgID);
|
||||||
size_t payloadSize = SSU_MTU - sizeof (SSUHeader) - 9; // 9 = flag + #frg(1) + messageID(4) + frag info (3)
|
size_t payloadSize = SSU_MTU - sizeof (SSUHeader) - 9; // 9 = flag + #frg(1) + messageID(4) + frag info (3)
|
||||||
size_t len = msg->GetLength ();
|
size_t len = msg->GetLength ();
|
||||||
|
@ -171,8 +252,9 @@ namespace ssu
|
||||||
uint32_t fragmentNum = 0;
|
uint32_t fragmentNum = 0;
|
||||||
while (len > 0)
|
while (len > 0)
|
||||||
{
|
{
|
||||||
uint8_t * buf = new uint8_t[SSU_MTU + 18];
|
Fragment * fragment = new Fragment;
|
||||||
fragments.push_back (buf);
|
uint8_t * buf = fragment->buf;
|
||||||
|
fragments.push_back (fragment);
|
||||||
uint8_t * payload = buf + sizeof (SSUHeader);
|
uint8_t * payload = buf + sizeof (SSUHeader);
|
||||||
*payload = DATA_FLAG_WANT_REPLY; // for compatibility
|
*payload = DATA_FLAG_WANT_REPLY; // for compatibility
|
||||||
payload++;
|
payload++;
|
||||||
|
@ -195,6 +277,7 @@ namespace ssu
|
||||||
size += payload - buf;
|
size += payload - buf;
|
||||||
if (size & 0x0F) // make sure 16 bytes boundary
|
if (size & 0x0F) // make sure 16 bytes boundary
|
||||||
size = ((size >> 4) + 1) << 4; // (/16 + 1)*16
|
size = ((size >> 4) + 1) << 4; // (/16 + 1)*16
|
||||||
|
fragment->len = size;
|
||||||
|
|
||||||
// encrypt message with session key
|
// encrypt message with session key
|
||||||
m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, size);
|
m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, size);
|
||||||
|
@ -228,6 +311,77 @@ namespace ssu
|
||||||
m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, 48);
|
m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, 48);
|
||||||
m_Session.Send (buf, 48);
|
m_Session.Send (buf, 48);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SSUData::SendFragmentAck (uint32_t msgID, int fragmentNum)
|
||||||
|
{
|
||||||
|
if (fragmentNum > 64)
|
||||||
|
{
|
||||||
|
LogPrint ("Fragment number ", fragmentNum, " exceeds 64");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint8_t buf[64 + 18];
|
||||||
|
uint8_t * payload = buf + sizeof (SSUHeader);
|
||||||
|
*payload = DATA_FLAG_ACK_BITFIELDS_INCLUDED; // flag
|
||||||
|
payload++;
|
||||||
|
*payload = 1; // number of ACK bitfields
|
||||||
|
payload++;
|
||||||
|
// one ack
|
||||||
|
*(uint32_t *)(payload) = htobe32 (msgID); // msgID
|
||||||
|
payload += 4;
|
||||||
|
div_t d = div (fragmentNum, 7);
|
||||||
|
memset (payload, 0x80, d.quot); // 0x80 means non-last
|
||||||
|
payload += d.quot;
|
||||||
|
*payload = 0x40 >> d.rem; // set corresponding bit
|
||||||
|
payload++;
|
||||||
|
*payload = 0; // number of fragments
|
||||||
|
|
||||||
|
size_t len = d.quot < 4 ? 48 : 64; // 48 = 37 + 7 + 4 (3+1)
|
||||||
|
// encrypt message with session key
|
||||||
|
m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, len);
|
||||||
|
m_Session.Send (buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSUData::ScheduleResend()
|
||||||
|
{
|
||||||
|
m_ResendTimer.cancel ();
|
||||||
|
m_ResendTimer.expires_from_now (boost::posix_time::seconds(RESEND_INTERVAL));
|
||||||
|
m_ResendTimer.async_wait (boost::bind (&SSUData::HandleResendTimer,
|
||||||
|
this, boost::asio::placeholders::error));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSUData::HandleResendTimer (const boost::system::error_code& ecode)
|
||||||
|
{
|
||||||
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
|
{
|
||||||
|
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
||||||
|
for (auto it = m_SentMessages.begin (); it != m_SentMessages.end ();)
|
||||||
|
{
|
||||||
|
if (ts >= it->second->nextResendTime)
|
||||||
|
{
|
||||||
|
bool isEmpty = true;
|
||||||
|
for (auto f: it->second->fragments)
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
isEmpty = false;
|
||||||
|
m_Session.Send (f->buf, f->len); // resend
|
||||||
|
}
|
||||||
|
|
||||||
|
it->second->numResends++;
|
||||||
|
if (isEmpty || it->second->numResends >= MAX_NUM_RESENDS)
|
||||||
|
{
|
||||||
|
delete it->second;
|
||||||
|
it = m_SentMessages.erase (it);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
if (!m_SentMessages.empty ())
|
||||||
|
ScheduleResend ();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
62
SSUData.h
62
SSUData.h
|
@ -2,8 +2,11 @@
|
||||||
#define SSU_DATA_H__
|
#define SSU_DATA_H__
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <string.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
#include <boost/asio.hpp>
|
||||||
#include "I2NPProtocol.h"
|
#include "I2NPProtocol.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
|
@ -11,6 +14,9 @@ namespace i2p
|
||||||
namespace ssu
|
namespace ssu
|
||||||
{
|
{
|
||||||
|
|
||||||
|
const size_t SSU_MTU = 1484;
|
||||||
|
const int RESEND_INTERVAL = 3; // in seconds
|
||||||
|
const int MAX_NUM_RESENDS = 5;
|
||||||
// data flags
|
// data flags
|
||||||
const uint8_t DATA_FLAG_EXTENDED_DATA_INCLUDED = 0x02;
|
const uint8_t DATA_FLAG_EXTENDED_DATA_INCLUDED = 0x02;
|
||||||
const uint8_t DATA_FLAG_WANT_REPLY = 0x04;
|
const uint8_t DATA_FLAG_WANT_REPLY = 0x04;
|
||||||
|
@ -19,6 +25,45 @@ namespace ssu
|
||||||
const uint8_t DATA_FLAG_ACK_BITFIELDS_INCLUDED = 0x40;
|
const uint8_t DATA_FLAG_ACK_BITFIELDS_INCLUDED = 0x40;
|
||||||
const uint8_t DATA_FLAG_EXPLICIT_ACKS_INCLUDED = 0x80;
|
const uint8_t DATA_FLAG_EXPLICIT_ACKS_INCLUDED = 0x80;
|
||||||
|
|
||||||
|
struct Fragment
|
||||||
|
{
|
||||||
|
int fragmentNum;
|
||||||
|
size_t len;
|
||||||
|
bool isLast;
|
||||||
|
uint8_t buf[SSU_MTU + 18];
|
||||||
|
|
||||||
|
Fragment () = default;
|
||||||
|
Fragment (int n, const uint8_t * b, int l, bool last):
|
||||||
|
fragmentNum (n), len (l), isLast (last) { memcpy (buf, b, len); };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FragmentCmp
|
||||||
|
{
|
||||||
|
bool operator() (const Fragment * f1, const Fragment * f2) const
|
||||||
|
{
|
||||||
|
return f1->fragmentNum < f2->fragmentNum;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IncompleteMessage
|
||||||
|
{
|
||||||
|
I2NPMessage * msg;
|
||||||
|
int nextFragmentNum;
|
||||||
|
std::set<Fragment *, FragmentCmp> savedFragments;
|
||||||
|
|
||||||
|
IncompleteMessage (I2NPMessage * m): msg (m), nextFragmentNum (0) {};
|
||||||
|
~IncompleteMessage () { for (auto it: savedFragments) { delete it; }; };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SentMessage
|
||||||
|
{
|
||||||
|
std::vector<Fragment *> fragments;
|
||||||
|
uint32_t nextResendTime; // in seconds
|
||||||
|
int numResends;
|
||||||
|
|
||||||
|
~SentMessage () { for (auto it: fragments) { delete it; }; };
|
||||||
|
};
|
||||||
|
|
||||||
class SSUSession;
|
class SSUSession;
|
||||||
class SSUData
|
class SSUData
|
||||||
{
|
{
|
||||||
|
@ -33,21 +78,20 @@ namespace ssu
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void SendMsgAck (uint32_t msgID);
|
void SendMsgAck (uint32_t msgID);
|
||||||
|
void SendFragmentAck (uint32_t msgID, int fragmentNum);
|
||||||
|
void ProcessAcks (uint8_t *& buf, uint8_t flag);
|
||||||
|
void ProcessFragments (uint8_t * buf);
|
||||||
void ProcessSentMessageAck (uint32_t msgID);
|
void ProcessSentMessageAck (uint32_t msgID);
|
||||||
|
|
||||||
|
void ScheduleResend ();
|
||||||
|
void HandleResendTimer (const boost::system::error_code& ecode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
struct IncompleteMessage
|
|
||||||
{
|
|
||||||
I2NPMessage * msg;
|
|
||||||
uint8_t nextFragmentNum;
|
|
||||||
|
|
||||||
IncompleteMessage (I2NPMessage * m): msg (m), nextFragmentNum (1) {};
|
|
||||||
};
|
|
||||||
|
|
||||||
SSUSession& m_Session;
|
SSUSession& m_Session;
|
||||||
std::map<uint32_t, IncompleteMessage *> m_IncomleteMessages;
|
std::map<uint32_t, IncompleteMessage *> m_IncomleteMessages;
|
||||||
std::map<uint32_t, std::vector<uint8_t *> > m_SentMessages; // msgID -> fragments
|
std::map<uint32_t, SentMessage *> m_SentMessages;
|
||||||
|
boost::asio::deadline_timer m_ResendTimer;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -263,6 +263,23 @@ namespace i2p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Transports::CloseSession (const i2p::data::RouterInfo * router)
|
||||||
|
{
|
||||||
|
if (!router) return;
|
||||||
|
m_Service.post (boost::bind (&Transports::PostCloseSession, this, router));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Transports::PostCloseSession (const i2p::data::RouterInfo * router)
|
||||||
|
{
|
||||||
|
auto ssuSession = m_SSUServer ? m_SSUServer->FindSession (router) : nullptr;
|
||||||
|
if (ssuSession) // try SSU first
|
||||||
|
{
|
||||||
|
m_SSUServer->DeleteSession (ssuSession);
|
||||||
|
LogPrint ("SSU session closed");
|
||||||
|
}
|
||||||
|
// TODO: delete NTCP
|
||||||
|
}
|
||||||
|
|
||||||
void Transports::DetectExternalIP ()
|
void Transports::DetectExternalIP ()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 5; i ++)
|
for (int i = 0; i < 5; i ++)
|
||||||
|
|
|
@ -63,12 +63,14 @@ namespace i2p
|
||||||
i2p::ntcp::NTCPSession * FindNTCPSession (const i2p::data::IdentHash& ident);
|
i2p::ntcp::NTCPSession * FindNTCPSession (const i2p::data::IdentHash& ident);
|
||||||
|
|
||||||
void SendMessage (const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg);
|
void SendMessage (const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg);
|
||||||
|
void CloseSession (const i2p::data::RouterInfo * router);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void Run ();
|
void Run ();
|
||||||
void HandleAccept (i2p::ntcp::NTCPServerConnection * conn, const boost::system::error_code& error);
|
void HandleAccept (i2p::ntcp::NTCPServerConnection * conn, const boost::system::error_code& error);
|
||||||
void PostMessage (const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg);
|
void PostMessage (const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg);
|
||||||
|
void PostCloseSession (const i2p::data::RouterInfo * router);
|
||||||
|
|
||||||
void DetectExternalIP ();
|
void DetectExternalIP ();
|
||||||
|
|
||||||
|
|
|
@ -361,10 +361,12 @@ namespace tunnel
|
||||||
void Tunnels::ManageTunnels ()
|
void Tunnels::ManageTunnels ()
|
||||||
{
|
{
|
||||||
// check pending tunnel. if something is still there, wipe it out
|
// check pending tunnel. if something is still there, wipe it out
|
||||||
// because it wouldn't be reponded anyway
|
// because it wouldn't be responded anyway
|
||||||
for (auto& it : m_PendingTunnels)
|
for (auto& it : m_PendingTunnels)
|
||||||
{
|
{
|
||||||
LogPrint ("Pending tunnel build request ", it.first, " has not been responded. Deleted");
|
LogPrint ("Pending tunnel build request ", it.first, " has not been responded. Deleted");
|
||||||
|
if (it.second->GetTunnelConfig ()->GetFirstHop ()->isGateway) // outbound
|
||||||
|
i2p::transports.CloseSession (it.second->GetTunnelConfig ()->GetFirstHop ()->router);
|
||||||
delete it.second;
|
delete it.second;
|
||||||
}
|
}
|
||||||
m_PendingTunnels.clear ();
|
m_PendingTunnels.clear ();
|
||||||
|
|
|
@ -188,7 +188,7 @@ namespace tunnel
|
||||||
hops.push_back (hop);
|
hops.push_back (hop);
|
||||||
}
|
}
|
||||||
std::reverse (hops.begin (), hops.end ());
|
std::reverse (hops.begin (), hops.end ());
|
||||||
auto * tunnel = tunnels.CreateTunnel<InboundTunnel> (new TunnelConfig (hops));
|
auto * tunnel = tunnels.CreateTunnel<InboundTunnel> (new TunnelConfig (hops), outboundTunnel);
|
||||||
tunnel->SetTunnelPool (this);
|
tunnel->SetTunnelPool (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
TEMPLATE = app
|
|
||||||
CONFIG += console
|
|
||||||
CONFIG -= app_bundle
|
|
||||||
CONFIG -= qt
|
|
||||||
|
|
||||||
TARGET = ./../../i2pd_qt
|
|
||||||
|
|
||||||
QMAKE_CXXFLAGS += -std=c++0x
|
|
||||||
|
|
||||||
LIBS += -lcrypto++
|
|
||||||
LIBS += \
|
|
||||||
-lboost_system\
|
|
||||||
-lboost_filesystem\
|
|
||||||
-lboost_regex\
|
|
||||||
-lboost_program_options\
|
|
||||||
-lpthread
|
|
||||||
|
|
||||||
SOURCES += \
|
|
||||||
../LeaseSet.cpp \
|
|
||||||
../i2p.cpp \
|
|
||||||
../HTTPServer.cpp \
|
|
||||||
../HTTPProxy.cpp \
|
|
||||||
../Garlic.cpp \
|
|
||||||
../base64.cpp \
|
|
||||||
../AddressBook.cpp \
|
|
||||||
../util.cpp \
|
|
||||||
../UPnP.cpp \
|
|
||||||
../TunnelPool.cpp \
|
|
||||||
../TunnelGateway.cpp \
|
|
||||||
../TunnelEndpoint.cpp \
|
|
||||||
../Tunnel.cpp \
|
|
||||||
../Transports.cpp \
|
|
||||||
../TransitTunnel.cpp \
|
|
||||||
../Streaming.cpp \
|
|
||||||
../SSU.cpp \
|
|
||||||
../RouterInfo.cpp \
|
|
||||||
../RouterContext.cpp \
|
|
||||||
../Reseed.cpp \
|
|
||||||
../NTCPSession.cpp \
|
|
||||||
../NetDb.cpp \
|
|
||||||
../Log.cpp \
|
|
||||||
../Identity.cpp \
|
|
||||||
../I2NPProtocol.cpp \
|
|
||||||
../SOCKS.cpp
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
../LeaseSet.h \
|
|
||||||
../Identity.h \
|
|
||||||
../HTTPServer.h \
|
|
||||||
../HTTPProxy.h \
|
|
||||||
../hmac.h \
|
|
||||||
../Garlic.h \
|
|
||||||
../ElGamal.h \
|
|
||||||
../CryptoConst.h \
|
|
||||||
../base64.h \
|
|
||||||
../AddressBook.h \
|
|
||||||
../util.h \
|
|
||||||
../UPnP.h \
|
|
||||||
../TunnelPool.h \
|
|
||||||
../TunnelGateway.h \
|
|
||||||
../TunnelEndpoint.h \
|
|
||||||
../TunnelConfig.h \
|
|
||||||
../TunnelBase.h \
|
|
||||||
../Tunnel.h \
|
|
||||||
../Transports.h \
|
|
||||||
../TransitTunnel.h \
|
|
||||||
../Timestamp.h \
|
|
||||||
../Streaming.h \
|
|
||||||
../SSU.h \
|
|
||||||
../RouterInfo.h \
|
|
||||||
../RouterContext.h \
|
|
||||||
../Reseed.h \
|
|
||||||
../Queue.h \
|
|
||||||
../NTCPSession.h \
|
|
||||||
../NetDb.h \
|
|
||||||
../Log.h \
|
|
||||||
../LittleBigEndian.h \
|
|
||||||
../I2PEndian.h \
|
|
||||||
../I2NPProtocol.h \
|
|
||||||
../SOCKS.h
|
|
||||||
|
|
||||||
OTHER_FILES += \
|
|
||||||
../README.md \
|
|
||||||
../Makefile \
|
|
||||||
../LICENSE
|
|
18
filelist.mk
Normal file
18
filelist.mk
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
|
||||||
|
CPP_FILES := CryptoConst.cpp base64.cpp NTCPSession.cpp RouterInfo.cpp Transports.cpp \
|
||||||
|
RouterContext.cpp NetDb.cpp LeaseSet.cpp Tunnel.cpp TunnelEndpoint.cpp TunnelGateway.cpp \
|
||||||
|
TransitTunnel.cpp I2NPProtocol.cpp Log.cpp Garlic.cpp HTTPServer.cpp Streaming.cpp Identity.cpp \
|
||||||
|
SSU.cpp util.cpp Reseed.cpp DaemonLinux.cpp SSUData.cpp i2p.cpp aes.cpp SOCKS.cpp UPnP.cpp \
|
||||||
|
TunnelPool.cpp HTTPProxy.cpp AddressBook.cpp Daemon.cpp
|
||||||
|
|
||||||
|
|
||||||
|
H_FILES := CryptoConst.h base64.h NTCPSession.h RouterInfo.h Transports.h \
|
||||||
|
RouterContext.h NetDb.h LeaseSet.h Tunnel.h TunnelEndpoint.h TunnelGateway.h \
|
||||||
|
TransitTunnel.h I2NPProtocol.h Log.h Garlic.h HTTPServer.h Streaming.h Identity.h \
|
||||||
|
SSU.h util.h Reseed.h DaemonLinux.h SSUData.h i2p.h aes.h SOCKS.h UPnP.h TunnelPool.h \
|
||||||
|
HTTPProxy.h AddressBook.h Daemon.h
|
||||||
|
|
||||||
|
|
||||||
|
OBJECTS = $(addprefix obj/, $(notdir $(CPP_FILES:.cpp=.o)))
|
||||||
|
|
Loading…
Reference in a new issue