mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-02 09:46:52 -05:00
i2p: use pointers to Sock to accommodate mocking
Change the types of `i2p::Connection::sock` and `i2p::sam::Session::m_control_sock` from `Sock` to `std::unique_ptr<Sock>`. Using pointers would allow us to sneak `FuzzedSock` instead of `Sock` and have the methods of the former called. After this change a test only needs to replace `CreateSock()` with a function that returns `FuzzedSock`.
This commit is contained in:
parent
82d360b5a8
commit
9947e44de0
3 changed files with 30 additions and 26 deletions
40
src/i2p.cpp
40
src/i2p.cpp
|
@ -20,6 +20,7 @@
|
|||
#include <util/system.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
|
@ -115,7 +116,8 @@ 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_private_key_file(private_key_file), m_control_host(control_host), m_interrupt(interrupt),
|
||||
m_control_sock(std::make_unique<Sock>(INVALID_SOCKET))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -145,7 +147,7 @@ bool Session::Accept(Connection& conn)
|
|||
try {
|
||||
while (!*m_interrupt) {
|
||||
Sock::Event occurred;
|
||||
conn.sock.Wait(MAX_WAIT_FOR_IO, Sock::RECV, &occurred);
|
||||
conn.sock->Wait(MAX_WAIT_FOR_IO, Sock::RECV, &occurred);
|
||||
|
||||
if ((occurred & Sock::RECV) == 0) {
|
||||
// Timeout, no incoming connections within MAX_WAIT_FOR_IO.
|
||||
|
@ -153,7 +155,7 @@ bool Session::Accept(Connection& conn)
|
|||
}
|
||||
|
||||
const std::string& peer_dest =
|
||||
conn.sock.RecvUntilTerminator('\n', MAX_WAIT_FOR_IO, *m_interrupt, MAX_MSG_SIZE);
|
||||
conn.sock->RecvUntilTerminator('\n', MAX_WAIT_FOR_IO, *m_interrupt, MAX_MSG_SIZE);
|
||||
|
||||
conn.peer = CService(DestB64ToAddr(peer_dest), Params().GetDefaultPort());
|
||||
|
||||
|
@ -171,7 +173,7 @@ bool Session::Connect(const CService& to, Connection& conn, bool& proxy_error)
|
|||
proxy_error = true;
|
||||
|
||||
std::string session_id;
|
||||
Sock sock;
|
||||
std::unique_ptr<Sock> sock;
|
||||
conn.peer = to;
|
||||
|
||||
try {
|
||||
|
@ -184,12 +186,12 @@ bool Session::Connect(const CService& to, Connection& conn, bool& proxy_error)
|
|||
}
|
||||
|
||||
const Reply& lookup_reply =
|
||||
SendRequestAndGetReply(sock, strprintf("NAMING LOOKUP NAME=%s", to.ToStringIP()));
|
||||
SendRequestAndGetReply(*sock, strprintf("NAMING LOOKUP NAME=%s", to.ToStringIP()));
|
||||
|
||||
const std::string& dest = lookup_reply.Get("VALUE");
|
||||
|
||||
const Reply& connect_reply = SendRequestAndGetReply(
|
||||
sock, strprintf("STREAM CONNECT ID=%s DESTINATION=%s SILENT=false", session_id, dest),
|
||||
*sock, strprintf("STREAM CONNECT ID=%s DESTINATION=%s SILENT=false", session_id, dest),
|
||||
false);
|
||||
|
||||
const std::string& result = connect_reply.Get("RESULT");
|
||||
|
@ -271,7 +273,7 @@ Session::Reply Session::SendRequestAndGetReply(const Sock& sock,
|
|||
return reply;
|
||||
}
|
||||
|
||||
Sock Session::Hello() const
|
||||
std::unique_ptr<Sock> Session::Hello() const
|
||||
{
|
||||
auto sock = CreateSock(m_control_host);
|
||||
|
||||
|
@ -285,7 +287,7 @@ Sock Session::Hello() const
|
|||
|
||||
SendRequestAndGetReply(*sock, "HELLO VERSION MIN=3.1 MAX=3.1");
|
||||
|
||||
return std::move(*sock);
|
||||
return sock;
|
||||
}
|
||||
|
||||
void Session::CheckControlSock()
|
||||
|
@ -293,7 +295,7 @@ void Session::CheckControlSock()
|
|||
LOCK(m_mutex);
|
||||
|
||||
std::string errmsg;
|
||||
if (!m_control_sock.IsConnected(errmsg)) {
|
||||
if (!m_control_sock->IsConnected(errmsg)) {
|
||||
Log("Control socket error: %s", errmsg);
|
||||
Disconnect();
|
||||
}
|
||||
|
@ -341,26 +343,26 @@ Binary Session::MyDestination() const
|
|||
void Session::CreateIfNotCreatedAlready()
|
||||
{
|
||||
std::string errmsg;
|
||||
if (m_control_sock.IsConnected(errmsg)) {
|
||||
if (m_control_sock->IsConnected(errmsg)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Log("Creating SAM session with %s", m_control_host.ToString());
|
||||
|
||||
Sock sock = Hello();
|
||||
auto sock = Hello();
|
||||
|
||||
const auto& [read_ok, data] = ReadBinaryFile(m_private_key_file);
|
||||
if (read_ok) {
|
||||
m_private_key.assign(data.begin(), data.end());
|
||||
} else {
|
||||
GenerateAndSavePrivateKey(sock);
|
||||
GenerateAndSavePrivateKey(*sock);
|
||||
}
|
||||
|
||||
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));
|
||||
SendRequestAndGetReply(*sock, strprintf("SESSION CREATE STYLE=STREAM ID=%s DESTINATION=%s",
|
||||
session_id, private_key_b64));
|
||||
|
||||
m_my_addr = CService(DestBinToAddr(MyDestination()), Params().GetDefaultPort());
|
||||
m_session_id = session_id;
|
||||
|
@ -370,12 +372,12 @@ void Session::CreateIfNotCreatedAlready()
|
|||
m_my_addr.ToString());
|
||||
}
|
||||
|
||||
Sock Session::StreamAccept()
|
||||
std::unique_ptr<Sock> Session::StreamAccept()
|
||||
{
|
||||
Sock sock = Hello();
|
||||
auto sock = Hello();
|
||||
|
||||
const Reply& reply = SendRequestAndGetReply(
|
||||
sock, strprintf("STREAM ACCEPT ID=%s SILENT=false", m_session_id), false);
|
||||
*sock, strprintf("STREAM ACCEPT ID=%s SILENT=false", m_session_id), false);
|
||||
|
||||
const std::string& result = reply.Get("RESULT");
|
||||
|
||||
|
@ -393,14 +395,14 @@ Sock Session::StreamAccept()
|
|||
|
||||
void Session::Disconnect()
|
||||
{
|
||||
if (m_control_sock.Get() != INVALID_SOCKET) {
|
||||
if (m_control_sock->Get() != INVALID_SOCKET) {
|
||||
if (m_session_id.empty()) {
|
||||
Log("Destroying incomplete session");
|
||||
} else {
|
||||
Log("Destroying session %s", m_session_id);
|
||||
}
|
||||
}
|
||||
m_control_sock.Reset();
|
||||
m_control_sock->Reset();
|
||||
m_session_id.clear();
|
||||
}
|
||||
} // namespace sam
|
||||
|
|
12
src/i2p.h
12
src/i2p.h
|
@ -12,6 +12,7 @@
|
|||
#include <threadinterrupt.h>
|
||||
#include <util/sock.h>
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
@ -29,7 +30,7 @@ using Binary = std::vector<uint8_t>;
|
|||
*/
|
||||
struct Connection {
|
||||
/** Connected socket. */
|
||||
Sock sock;
|
||||
std::unique_ptr<Sock> sock;
|
||||
|
||||
/** Our I2P address. */
|
||||
CService me;
|
||||
|
@ -166,7 +167,7 @@ private:
|
|||
* @return a connected socket
|
||||
* @throws std::runtime_error if an error occurs
|
||||
*/
|
||||
Sock Hello() const EXCLUSIVE_LOCKS_REQUIRED(m_mutex);
|
||||
std::unique_ptr<Sock> Hello() const EXCLUSIVE_LOCKS_REQUIRED(m_mutex);
|
||||
|
||||
/**
|
||||
* Check the control socket for errors and possibly disconnect.
|
||||
|
@ -204,10 +205,11 @@ private:
|
|||
|
||||
/**
|
||||
* Open a new connection to the SAM proxy and issue "STREAM ACCEPT" request using the existing
|
||||
* session id. Return the idle socket that is waiting for a peer to connect to us.
|
||||
* session id.
|
||||
* @return the idle socket that is waiting for a peer to connect to us
|
||||
* @throws std::runtime_error if an error occurs
|
||||
*/
|
||||
Sock StreamAccept() EXCLUSIVE_LOCKS_REQUIRED(m_mutex);
|
||||
std::unique_ptr<Sock> StreamAccept() EXCLUSIVE_LOCKS_REQUIRED(m_mutex);
|
||||
|
||||
/**
|
||||
* Destroy the session, closing the internally used sockets.
|
||||
|
@ -248,7 +250,7 @@ private:
|
|||
* connections and make outgoing ones.
|
||||
* See https://geti2p.net/en/docs/api/samv3
|
||||
*/
|
||||
Sock m_control_sock GUARDED_BY(m_mutex);
|
||||
std::unique_ptr<Sock> m_control_sock GUARDED_BY(m_mutex);
|
||||
|
||||
/**
|
||||
* Our .b32.i2p address.
|
||||
|
|
|
@ -432,7 +432,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
|
|||
i2p::Connection conn;
|
||||
if (m_i2p_sam_session->Connect(addrConnect, conn, proxyConnectionFailed)) {
|
||||
connected = true;
|
||||
sock = std::make_unique<Sock>(std::move(conn.sock));
|
||||
sock = std::move(conn.sock);
|
||||
addr_bind = CAddress{conn.me, NODE_NONE};
|
||||
}
|
||||
} else if (GetProxy(addrConnect.GetNetwork(), proxy)) {
|
||||
|
@ -2221,7 +2221,7 @@ void CConnman::ThreadI2PAcceptIncoming()
|
|||
continue;
|
||||
}
|
||||
|
||||
CreateNodeFromAcceptedSocket(conn.sock.Release(), NetPermissionFlags::PF_NONE,
|
||||
CreateNodeFromAcceptedSocket(conn.sock->Release(), NetPermissionFlags::PF_NONE,
|
||||
CAddress{conn.me, NODE_NONE}, CAddress{conn.peer, NODE_NONE});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue