Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F10615197
i2p.h
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
9 KB
Subscribers
None
i2p.h
View Options
// Copyright (c) 2020-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_I2P_H
#define BITCOIN_I2P_H
#include
<compat.h>
#include
<fs.h>
#include
<netaddress.h>
#include
<sync.h>
#include
<threadinterrupt.h>
#include
<util/sock.h>
#include
<memory>
#include
<optional>
#include
<string>
#include
<unordered_map>
#include
<vector>
namespace
i2p
{
/**
* Binary data.
*/
using
Binary
=
std
::
vector
<
uint8_t
>
;
/**
* An established connection with another peer.
*/
struct
Connection
{
/** Connected socket. */
std
::
unique_ptr
<
Sock
>
sock
;
/** Our I2P address. */
CService
me
;
/** The peer's I2P address. */
CService
peer
;
};
namespace
sam
{
/**
* The maximum size of an incoming message from the I2P SAM proxy (in
* bytes). Used to avoid a runaway proxy from sending us an "unlimited"
* amount of data without a terminator. The longest known message is ~1400
* bytes, so this is high enough not to be triggered during normal
* operation, yet low enough to avoid a malicious proxy from filling our
* memory.
*/
static
constexpr
size_t
MAX_MSG_SIZE
{
65536
};
/**
* I2P SAM session.
*/
class
Session
{
public
:
/**
* Construct a session. This will not initiate any IO, the session will
* be lazily created later when first used.
* @param[in] private_key_file Path to a private key file. If the file
* does not exist then the private key will be generated and saved into
* the file.
* @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
fs
::
path
&
private_key_file
,
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 the SAM proxy because the session
* is destroyed. So they will return an error next time we try to read
* or write to them.
*/
~
Session
();
/**
* Start listening for an incoming connection.
* @param[out] conn Upon successful completion the `sock` and `me`
* members will be set to the listening socket and address.
* @return true on success
*/
bool
Listen
(
Connection
&
conn
);
/**
* Wait for and accept a new incoming connection.
* @param[in,out] conn The `sock` member is used for waiting and
* accepting. Upon successful completion the `peer` member will be set
* to the address of the incoming peer.
* @return true on success
*/
bool
Accept
(
Connection
&
conn
);
/**
* Connect to an I2P peer.
* @param[in] to Peer to connect to.
* @param[out] conn Established connection. Only set if `true` is
* returned.
* @param[out] proxy_error If an error occurs due to proxy or general
* network failure, then this is set to `true`. If an error occurs due
* to unreachable peer (likely peer is down), then it is set to `false`.
* Only set if `false` is returned.
* @return true on success
*/
bool
Connect
(
const
CService
&
to
,
Connection
&
conn
,
bool
&
proxy_error
);
private
:
/**
* A reply from the SAM proxy.
*/
struct
Reply
{
/**
* Full, unparsed reply.
*/
std
::
string
full
;
/**
* Request, used for detailed error reporting.
*/
std
::
string
request
;
/**
* A map of keywords from the parsed reply.
* For example, if the reply is "A=X B C=YZ", then the map will be
* keys["A"] == "X"
* keys["B"] == (empty std::optional)
* keys["C"] == "YZ"
*/
std
::
unordered_map
<
std
::
string
,
std
::
optional
<
std
::
string
>>
keys
;
/**
* Get the value of a given key.
* For example if the reply is "A=X B" then:
* Value("A") -> "X"
* Value("B") -> throws
* Value("C") -> throws
* @param[in] key Key whose value to retrieve
* @returns the key's value
* @throws std::runtime_error if the key is not present or if it has
* no value
*/
std
::
string
Get
(
const
std
::
string
&
key
)
const
;
};
/**
* Log a message in the `BCLog::I2P` category.
* @param[in] fmt printf(3)-like format string.
* @param[in] args printf(3)-like arguments that correspond to `fmt`.
*/
template
<
typename
...
Args
>
void
Log
(
const
std
::
string
&
fmt
,
const
Args
&
...
args
)
const
;
/**
* Send request and get a reply from the SAM proxy.
* @param[in] sock A socket that is connected to the SAM proxy.
* @param[in] request Raw request to send, a newline terminator is
* appended to it.
* @param[in] check_result_ok If true then after receiving the reply a
* check is made whether it contains "RESULT=OK" and an exception is
* thrown if it does not.
* @throws std::runtime_error if an error occurs
*/
Reply
SendRequestAndGetReply
(
const
Sock
&
sock
,
const
std
::
string
&
request
,
bool
check_result_ok
=
true
)
const
;
/**
* Open a new connection to the SAM proxy.
* @return a connected socket
* @throws std::runtime_error if an error occurs
*/
std
::
unique_ptr
<
Sock
>
Hello
()
const
EXCLUSIVE_LOCKS_REQUIRED
(
m_mutex
);
/**
* Check the control socket for errors and possibly disconnect.
*/
void
CheckControlSock
();
/**
* Generate a new destination with the SAM proxy and set `m_private_key`
* to it.
* @param[in] sock Socket to use for talking to the SAM proxy.
* @throws std::runtime_error if an error occurs
*/
void
DestGenerate
(
const
Sock
&
sock
)
EXCLUSIVE_LOCKS_REQUIRED
(
m_mutex
);
/**
* Generate a new destination with the SAM proxy, set `m_private_key` to
* it and save it on disk to `m_private_key_file`.
* @param[in] sock Socket to use for talking to the SAM proxy.
* @throws std::runtime_error if an error occurs
*/
void
GenerateAndSavePrivateKey
(
const
Sock
&
sock
)
EXCLUSIVE_LOCKS_REQUIRED
(
m_mutex
);
/**
* Derive own destination from `m_private_key`.
* @see https://geti2p.net/spec/common-structures#destination
* @return an I2P destination
*/
Binary
MyDestination
()
const
EXCLUSIVE_LOCKS_REQUIRED
(
m_mutex
);
/**
* Create the session if not already created. Reads the private key file
* and connects to the SAM proxy.
* @throws std::runtime_error if an error occurs
*/
void
CreateIfNotCreatedAlready
()
EXCLUSIVE_LOCKS_REQUIRED
(
m_mutex
);
/**
* 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
* @throws std::runtime_error if an error occurs
*/
std
::
unique_ptr
<
Sock
>
StreamAccept
()
EXCLUSIVE_LOCKS_REQUIRED
(
m_mutex
);
/**
* Destroy the session, closing the internally used sockets.
*/
void
Disconnect
()
EXCLUSIVE_LOCKS_REQUIRED
(
m_mutex
);
/**
* The name of the file where this peer's private key is stored (in
* binary).
*/
const
fs
::
path
m_private_key_file
;
/**
* The host and port of the SAM control service.
*/
const
CService
m_control_host
;
/**
* Cease network activity when this is signaled.
*/
CThreadInterrupt
*
const
m_interrupt
;
/**
* Mutex protecting the members that can be concurrently accessed.
*/
mutable
Mutex
m_mutex
;
/**
* The private key of this peer.
* @see The reply to the "DEST GENERATE" command in
* https://geti2p.net/en/docs/api/samv3
*/
Binary
m_private_key
GUARDED_BY
(
m_mutex
);
/**
* SAM control socket.
* Used to connect to the I2P SAM service and create a session
* ("SESSION CREATE"). With the established session id we later open
* other connections to the SAM service to accept incoming I2P
* connections and make outgoing ones.
* See https://geti2p.net/en/docs/api/samv3
*/
std
::
unique_ptr
<
Sock
>
m_control_sock
GUARDED_BY
(
m_mutex
);
/**
* Our .b32.i2p address.
* Derived from `m_private_key`.
*/
CService
m_my_addr
GUARDED_BY
(
m_mutex
);
/**
* SAM session id.
*/
std
::
string
m_session_id
GUARDED_BY
(
m_mutex
);
};
}
// namespace sam
}
// namespace i2p
#endif
// BITCOIN_I2P_H
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Sat, Nov 23, 10:01 (1 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4514311
Default Alt Text
i2p.h (9 KB)
Attached To
rSTAGING Bitcoin ABC staging
Event Timeline
Log In to Comment