aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVasil Dimov <vd@FreeBSD.org>2021-03-04 14:31:49 +0100
committerVasil Dimov <vd@FreeBSD.org>2021-03-16 13:59:18 +0100
commit9947e44de0cbd79e99d883443a9ac441d8c69713 (patch)
tree8d60e4c979aa3fe1cf383e108a4b35b42df63614 /src
parent82d360b5a88d9057b6c09b61cd69e426c7a2412d (diff)
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`.
Diffstat (limited to 'src')
-rw-r--r--src/i2p.cpp40
-rw-r--r--src/i2p.h12
-rw-r--r--src/net.cpp4
3 files changed, 30 insertions, 26 deletions
diff --git a/src/i2p.cpp b/src/i2p.cpp
index 13e7ce3515..a44f09f043 100644
--- a/src/i2p.cpp
+++ b/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
diff --git a/src/i2p.h b/src/i2p.h
index 1ebe7d0329..cb2efedba8 100644
--- a/src/i2p.h
+++ b/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.
diff --git a/src/net.cpp b/src/net.cpp
index 36065118d7..6ff51057b1 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -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});
}
}