mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-02 09:46:52 -05:00
i2p: add support for creating transient sessions
Instead of providing our destination (private key) to the I2P proxy when creating the session, ask it to generate one for us and do not save it on disk.
This commit is contained in:
parent
c012875b9d
commit
2b781ad66e
3 changed files with 65 additions and 17 deletions
61
src/i2p.cpp
61
src/i2p.cpp
|
@ -12,11 +12,11 @@
|
|||
#include <netaddress.h>
|
||||
#include <netbase.h>
|
||||
#include <random.h>
|
||||
#include <util/strencodings.h>
|
||||
#include <tinyformat.h>
|
||||
#include <util/readwritefile.h>
|
||||
#include <util/sock.h>
|
||||
#include <util/spanparsing.h>
|
||||
#include <util/strencodings.h>
|
||||
#include <util/system.h>
|
||||
|
||||
#include <chrono>
|
||||
|
@ -115,8 +115,19 @@ namespace sam {
|
|||
Session::Session(const fs::path& private_key_file,
|
||||
const CService& control_host,
|
||||
CThreadInterrupt* interrupt)
|
||||
: m_private_key_file(private_key_file), m_control_host(control_host), m_interrupt(interrupt),
|
||||
m_control_sock(std::make_unique<Sock>(INVALID_SOCKET))
|
||||
: m_private_key_file{private_key_file},
|
||||
m_control_host{control_host},
|
||||
m_interrupt{interrupt},
|
||||
m_control_sock{std::make_unique<Sock>(INVALID_SOCKET)},
|
||||
m_transient{false}
|
||||
{
|
||||
}
|
||||
|
||||
Session::Session(const CService& control_host, CThreadInterrupt* interrupt)
|
||||
: m_control_host{control_host},
|
||||
m_interrupt{interrupt},
|
||||
m_control_sock{std::make_unique<Sock>(INVALID_SOCKET)},
|
||||
m_transient{true}
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -355,29 +366,47 @@ void Session::CreateIfNotCreatedAlready()
|
|||
return;
|
||||
}
|
||||
|
||||
Log("Creating SAM session with %s", m_control_host.ToString());
|
||||
const auto session_type = m_transient ? "transient" : "persistent";
|
||||
const auto session_id = GetRandHash().GetHex().substr(0, 10); // full is overkill, too verbose in the logs
|
||||
|
||||
Log("Creating %s SAM session %s with %s", session_type, session_id, m_control_host.ToString());
|
||||
|
||||
auto sock = Hello();
|
||||
|
||||
const auto& [read_ok, data] = ReadBinaryFile(m_private_key_file);
|
||||
if (read_ok) {
|
||||
m_private_key.assign(data.begin(), data.end());
|
||||
if (m_transient) {
|
||||
// The destination (private key) is generated upon session creation and returned
|
||||
// in the reply in DESTINATION=.
|
||||
const Reply& reply = SendRequestAndGetReply(
|
||||
*sock,
|
||||
strprintf("SESSION CREATE STYLE=STREAM ID=%s DESTINATION=TRANSIENT", session_id));
|
||||
|
||||
m_private_key = DecodeI2PBase64(reply.Get("DESTINATION"));
|
||||
} else {
|
||||
GenerateAndSavePrivateKey(*sock);
|
||||
// Read our persistent destination (private key) from disk or generate
|
||||
// one and save it to disk. Then use it when creating the session.
|
||||
const auto& [read_ok, data] = ReadBinaryFile(m_private_key_file);
|
||||
if (read_ok) {
|
||||
m_private_key.assign(data.begin(), data.end());
|
||||
} else {
|
||||
GenerateAndSavePrivateKey(*sock);
|
||||
}
|
||||
|
||||
const std::string& private_key_b64 = SwapBase64(EncodeBase64(m_private_key));
|
||||
|
||||
SendRequestAndGetReply(*sock,
|
||||
strprintf("SESSION CREATE STYLE=STREAM ID=%s DESTINATION=%s",
|
||||
session_id,
|
||||
private_key_b64));
|
||||
}
|
||||
|
||||
const std::string& session_id = GetRandHash().GetHex().substr(0, 10); // full is an overkill, too verbose in the logs
|
||||
const std::string& private_key_b64 = SwapBase64(EncodeBase64(m_private_key));
|
||||
|
||||
SendRequestAndGetReply(*sock, strprintf("SESSION CREATE STYLE=STREAM ID=%s DESTINATION=%s",
|
||||
session_id, private_key_b64));
|
||||
|
||||
m_my_addr = CService(DestBinToAddr(MyDestination()), I2P_SAM31_PORT);
|
||||
m_session_id = session_id;
|
||||
m_control_sock = std::move(sock);
|
||||
|
||||
LogPrintfCategory(BCLog::I2P, "SAM session created: session id=%s, my address=%s\n",
|
||||
m_session_id, m_my_addr.ToString());
|
||||
Log("%s SAM session %s created, my address=%s",
|
||||
Capitalize(session_type),
|
||||
m_session_id,
|
||||
m_my_addr.ToString());
|
||||
}
|
||||
|
||||
std::unique_ptr<Sock> Session::StreamAccept()
|
||||
|
|
19
src/i2p.h
19
src/i2p.h
|
@ -70,6 +70,19 @@ public:
|
|||
const CService& control_host,
|
||||
CThreadInterrupt* interrupt);
|
||||
|
||||
/**
|
||||
* Construct a transient session which will generate its own I2P private key
|
||||
* rather than read the one from disk (it will not be saved on disk either and
|
||||
* will be lost once this object is destroyed). This will not initiate any IO,
|
||||
* the session will be lazily created later when first used.
|
||||
* @param[in] control_host Location of the SAM proxy.
|
||||
* @param[in,out] interrupt If this is signaled then all operations are canceled as soon as
|
||||
* possible and executing methods throw an exception. Notice: only a pointer to the
|
||||
* `CThreadInterrupt` object is saved, so it must not be destroyed earlier than this
|
||||
* `Session` object.
|
||||
*/
|
||||
Session(const CService& control_host, CThreadInterrupt* interrupt);
|
||||
|
||||
/**
|
||||
* Destroy the session, closing the internally used sockets. The sockets that have been
|
||||
* returned by `Accept()` or `Connect()` will not be closed, but they will be closed by
|
||||
|
@ -262,6 +275,12 @@ private:
|
|||
* SAM session id.
|
||||
*/
|
||||
std::string m_session_id GUARDED_BY(m_mutex);
|
||||
|
||||
/**
|
||||
* Whether this is a transient session (the I2P private key will not be
|
||||
* read or written to disk).
|
||||
*/
|
||||
const bool m_transient;
|
||||
};
|
||||
|
||||
} // namespace sam
|
||||
|
|
|
@ -30,7 +30,7 @@ BOOST_AUTO_TEST_CASE(unlimited_recv)
|
|||
i2p::sam::Session session(gArgs.GetDataDirNet() / "test_i2p_private_key", CService{}, &interrupt);
|
||||
|
||||
{
|
||||
ASSERT_DEBUG_LOG("Creating SAM session");
|
||||
ASSERT_DEBUG_LOG("Creating persistent SAM session");
|
||||
ASSERT_DEBUG_LOG("too many bytes without a terminator");
|
||||
|
||||
i2p::Connection conn;
|
||||
|
|
Loading…
Add table
Reference in a new issue