aboutsummaryrefslogtreecommitdiff
path: root/src/torcontrol.h
diff options
context:
space:
mode:
authorpracticalswift <practicalswift@users.noreply.github.com>2020-10-06 19:01:37 +0000
committerpracticalswift <practicalswift@users.noreply.github.com>2021-03-02 12:21:32 +0000
commit64219c01dcb0aec6ca26170c94223bd7a29dad19 (patch)
tree0cdf01428401e5e8e0ebde23823d8cbec6062c47 /src/torcontrol.h
parentb9f41df1ead4b6a83a51fc41966b111c8459c313 (diff)
downloadbitcoin-64219c01dcb0aec6ca26170c94223bd7a29dad19.tar.xz
torcontrol: Move TorControlReply, TorControlConnection and TorController to improve testability
Diffstat (limited to 'src/torcontrol.h')
-rw-r--r--src/torcontrol.h132
1 files changed, 132 insertions, 0 deletions
diff --git a/src/torcontrol.h b/src/torcontrol.h
index 00f19db6ae..ecf26d89c1 100644
--- a/src/torcontrol.h
+++ b/src/torcontrol.h
@@ -8,7 +8,19 @@
#ifndef BITCOIN_TORCONTROL_H
#define BITCOIN_TORCONTROL_H
+#include <fs.h>
+#include <netaddress.h>
+
+#include <boost/signals2/signal.hpp>
+
+#include <event2/bufferevent.h>
+#include <event2/event.h>
+
+#include <cstdlib>
+#include <deque>
+#include <functional>
#include <string>
+#include <vector>
class CService;
@@ -21,4 +33,124 @@ void StopTorControl();
CService DefaultOnionServiceTarget();
+/** Reply from Tor, can be single or multi-line */
+class TorControlReply
+{
+public:
+ TorControlReply() { Clear(); }
+
+ int code;
+ std::vector<std::string> lines;
+
+ void Clear()
+ {
+ code = 0;
+ lines.clear();
+ }
+};
+
+/** Low-level handling for Tor control connection.
+ * Speaks the SMTP-like protocol as defined in torspec/control-spec.txt
+ */
+class TorControlConnection
+{
+public:
+ typedef std::function<void(TorControlConnection&)> ConnectionCB;
+ typedef std::function<void(TorControlConnection &,const TorControlReply &)> ReplyHandlerCB;
+
+ /** Create a new TorControlConnection.
+ */
+ explicit TorControlConnection(struct event_base *base);
+ ~TorControlConnection();
+
+ /**
+ * Connect to a Tor control port.
+ * tor_control_center is address of the form host:port.
+ * connected is the handler that is called when connection is successfully established.
+ * disconnected is a handler that is called when the connection is broken.
+ * Return true on success.
+ */
+ bool Connect(const std::string& tor_control_center, const ConnectionCB& connected, const ConnectionCB& disconnected);
+
+ /**
+ * Disconnect from Tor control port.
+ */
+ void Disconnect();
+
+ /** Send a command, register a handler for the reply.
+ * A trailing CRLF is automatically added.
+ * Return true on success.
+ */
+ bool Command(const std::string &cmd, const ReplyHandlerCB& reply_handler);
+
+ /** Response handlers for async replies */
+ boost::signals2::signal<void(TorControlConnection &,const TorControlReply &)> async_handler;
+private:
+ /** Callback when ready for use */
+ std::function<void(TorControlConnection&)> connected;
+ /** Callback when connection lost */
+ std::function<void(TorControlConnection&)> disconnected;
+ /** Libevent event base */
+ struct event_base *base;
+ /** Connection to control socket */
+ struct bufferevent *b_conn;
+ /** Message being received */
+ TorControlReply message;
+ /** Response handlers */
+ std::deque<ReplyHandlerCB> reply_handlers;
+
+ /** Libevent handlers: internal */
+ static void readcb(struct bufferevent *bev, void *ctx);
+ static void eventcb(struct bufferevent *bev, short what, void *ctx);
+};
+
+/****** Bitcoin specific TorController implementation ********/
+
+/** Controller that connects to Tor control socket, authenticate, then create
+ * and maintain an ephemeral onion service.
+ */
+class TorController
+{
+public:
+ TorController(struct event_base* base, const std::string& tor_control_center, const CService& target);
+ ~TorController();
+
+ /** Get name of file to store private key in */
+ fs::path GetPrivateKeyFile();
+
+ /** Reconnect, after getting disconnected */
+ void Reconnect();
+private:
+ struct event_base* base;
+ const std::string m_tor_control_center;
+ TorControlConnection conn;
+ std::string private_key;
+ std::string service_id;
+ bool reconnect;
+ struct event *reconnect_ev;
+ float reconnect_timeout;
+ CService service;
+ const CService m_target;
+ /** Cookie for SAFECOOKIE auth */
+ std::vector<uint8_t> cookie;
+ /** ClientNonce for SAFECOOKIE auth */
+ std::vector<uint8_t> clientNonce;
+
+ /** Callback for ADD_ONION result */
+ void add_onion_cb(TorControlConnection& conn, const TorControlReply& reply);
+ /** Callback for AUTHENTICATE result */
+ void auth_cb(TorControlConnection& conn, const TorControlReply& reply);
+ /** Callback for AUTHCHALLENGE result */
+ void authchallenge_cb(TorControlConnection& conn, const TorControlReply& reply);
+ /** Callback for PROTOCOLINFO result */
+ void protocolinfo_cb(TorControlConnection& conn, const TorControlReply& reply);
+ /** Callback after successful connection */
+ void connected_cb(TorControlConnection& conn);
+ /** Callback after connection lost or failed connection attempt */
+ void disconnected_cb(TorControlConnection& conn);
+
+ /** Callback for reconnect timer */
+ static void reconnect_cb(evutil_socket_t fd, short what, void *arg);
+};
+
#endif /* BITCOIN_TORCONTROL_H */