Skip to content

Commit 64219c0

Browse files
torcontrol: Move TorControlReply, TorControlConnection and TorController to improve testability
1 parent b9f41df commit 64219c0

File tree

2 files changed

+132
-120
lines changed

2 files changed

+132
-120
lines changed

src/torcontrol.cpp

Lines changed: 0 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -56,77 +56,6 @@ static const int MAX_LINE_LENGTH = 100000;
5656

5757
/****** Low-level TorControlConnection ********/
5858

59-
/** Reply from Tor, can be single or multi-line */
60-
class TorControlReply
61-
{
62-
public:
63-
TorControlReply() { Clear(); }
64-
65-
int code;
66-
std::vector<std::string> lines;
67-
68-
void Clear()
69-
{
70-
code = 0;
71-
lines.clear();
72-
}
73-
};
74-
75-
/** Low-level handling for Tor control connection.
76-
* Speaks the SMTP-like protocol as defined in torspec/control-spec.txt
77-
*/
78-
class TorControlConnection
79-
{
80-
public:
81-
typedef std::function<void(TorControlConnection&)> ConnectionCB;
82-
typedef std::function<void(TorControlConnection &,const TorControlReply &)> ReplyHandlerCB;
83-
84-
/** Create a new TorControlConnection.
85-
*/
86-
explicit TorControlConnection(struct event_base *base);
87-
~TorControlConnection();
88-
89-
/**
90-
* Connect to a Tor control port.
91-
* tor_control_center is address of the form host:port.
92-
* connected is the handler that is called when connection is successfully established.
93-
* disconnected is a handler that is called when the connection is broken.
94-
* Return true on success.
95-
*/
96-
bool Connect(const std::string& tor_control_center, const ConnectionCB& connected, const ConnectionCB& disconnected);
97-
98-
/**
99-
* Disconnect from Tor control port.
100-
*/
101-
void Disconnect();
102-
103-
/** Send a command, register a handler for the reply.
104-
* A trailing CRLF is automatically added.
105-
* Return true on success.
106-
*/
107-
bool Command(const std::string &cmd, const ReplyHandlerCB& reply_handler);
108-
109-
/** Response handlers for async replies */
110-
boost::signals2::signal<void(TorControlConnection &,const TorControlReply &)> async_handler;
111-
private:
112-
/** Callback when ready for use */
113-
std::function<void(TorControlConnection&)> connected;
114-
/** Callback when connection lost */
115-
std::function<void(TorControlConnection&)> disconnected;
116-
/** Libevent event base */
117-
struct event_base *base;
118-
/** Connection to control socket */
119-
struct bufferevent *b_conn;
120-
/** Message being received */
121-
TorControlReply message;
122-
/** Response handlers */
123-
std::deque<ReplyHandlerCB> reply_handlers;
124-
125-
/** Libevent handlers: internal */
126-
static void readcb(struct bufferevent *bev, void *ctx);
127-
static void eventcb(struct bufferevent *bev, short what, void *ctx);
128-
};
129-
13059
TorControlConnection::TorControlConnection(struct event_base *_base):
13160
base(_base), b_conn(nullptr)
13261
{
@@ -363,55 +292,6 @@ std::map<std::string,std::string> ParseTorReplyMapping(const std::string &s)
363292
return mapping;
364293
}
365294

366-
/****** Bitcoin specific TorController implementation ********/
367-
368-
/** Controller that connects to Tor control socket, authenticate, then create
369-
* and maintain an ephemeral onion service.
370-
*/
371-
class TorController
372-
{
373-
public:
374-
TorController(struct event_base* base, const std::string& tor_control_center, const CService& target);
375-
~TorController();
376-
377-
/** Get name of file to store private key in */
378-
fs::path GetPrivateKeyFile();
379-
380-
/** Reconnect, after getting disconnected */
381-
void Reconnect();
382-
private:
383-
struct event_base* base;
384-
const std::string m_tor_control_center;
385-
TorControlConnection conn;
386-
std::string private_key;
387-
std::string service_id;
388-
bool reconnect;
389-
struct event *reconnect_ev;
390-
float reconnect_timeout;
391-
CService service;
392-
const CService m_target;
393-
/** Cookie for SAFECOOKIE auth */
394-
std::vector<uint8_t> cookie;
395-
/** ClientNonce for SAFECOOKIE auth */
396-
std::vector<uint8_t> clientNonce;
397-
398-
/** Callback for ADD_ONION result */
399-
void add_onion_cb(TorControlConnection& conn, const TorControlReply& reply);
400-
/** Callback for AUTHENTICATE result */
401-
void auth_cb(TorControlConnection& conn, const TorControlReply& reply);
402-
/** Callback for AUTHCHALLENGE result */
403-
void authchallenge_cb(TorControlConnection& conn, const TorControlReply& reply);
404-
/** Callback for PROTOCOLINFO result */
405-
void protocolinfo_cb(TorControlConnection& conn, const TorControlReply& reply);
406-
/** Callback after successful connection */
407-
void connected_cb(TorControlConnection& conn);
408-
/** Callback after connection lost or failed connection attempt */
409-
void disconnected_cb(TorControlConnection& conn);
410-
411-
/** Callback for reconnect timer */
412-
static void reconnect_cb(evutil_socket_t fd, short what, void *arg);
413-
};
414-
415295
TorController::TorController(struct event_base* _base, const std::string& tor_control_center, const CService& target):
416296
base(_base),
417297
m_tor_control_center(tor_control_center), conn(base), reconnect(true), reconnect_ev(0),

src/torcontrol.h

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,19 @@
88
#ifndef BITCOIN_TORCONTROL_H
99
#define BITCOIN_TORCONTROL_H
1010

11+
#include <fs.h>
12+
#include <netaddress.h>
13+
14+
#include <boost/signals2/signal.hpp>
15+
16+
#include <event2/bufferevent.h>
17+
#include <event2/event.h>
18+
19+
#include <cstdlib>
20+
#include <deque>
21+
#include <functional>
1122
#include <string>
23+
#include <vector>
1224

1325
class CService;
1426

@@ -21,4 +33,124 @@ void StopTorControl();
2133

2234
CService DefaultOnionServiceTarget();
2335

36+
/** Reply from Tor, can be single or multi-line */
37+
class TorControlReply
38+
{
39+
public:
40+
TorControlReply() { Clear(); }
41+
42+
int code;
43+
std::vector<std::string> lines;
44+
45+
void Clear()
46+
{
47+
code = 0;
48+
lines.clear();
49+
}
50+
};
51+
52+
/** Low-level handling for Tor control connection.
53+
* Speaks the SMTP-like protocol as defined in torspec/control-spec.txt
54+
*/
55+
class TorControlConnection
56+
{
57+
public:
58+
typedef std::function<void(TorControlConnection&)> ConnectionCB;
59+
typedef std::function<void(TorControlConnection &,const TorControlReply &)> ReplyHandlerCB;
60+
61+
/** Create a new TorControlConnection.
62+
*/
63+
explicit TorControlConnection(struct event_base *base);
64+
~TorControlConnection();
65+
66+
/**
67+
* Connect to a Tor control port.
68+
* tor_control_center is address of the form host:port.
69+
* connected is the handler that is called when connection is successfully established.
70+
* disconnected is a handler that is called when the connection is broken.
71+
* Return true on success.
72+
*/
73+
bool Connect(const std::string& tor_control_center, const ConnectionCB& connected, const ConnectionCB& disconnected);
74+
75+
/**
76+
* Disconnect from Tor control port.
77+
*/
78+
void Disconnect();
79+
80+
/** Send a command, register a handler for the reply.
81+
* A trailing CRLF is automatically added.
82+
* Return true on success.
83+
*/
84+
bool Command(const std::string &cmd, const ReplyHandlerCB& reply_handler);
85+
86+
/** Response handlers for async replies */
87+
boost::signals2::signal<void(TorControlConnection &,const TorControlReply &)> async_handler;
88+
private:
89+
/** Callback when ready for use */
90+
std::function<void(TorControlConnection&)> connected;
91+
/** Callback when connection lost */
92+
std::function<void(TorControlConnection&)> disconnected;
93+
/** Libevent event base */
94+
struct event_base *base;
95+
/** Connection to control socket */
96+
struct bufferevent *b_conn;
97+
/** Message being received */
98+
TorControlReply message;
99+
/** Response handlers */
100+
std::deque<ReplyHandlerCB> reply_handlers;
101+
102+
/** Libevent handlers: internal */
103+
static void readcb(struct bufferevent *bev, void *ctx);
104+
static void eventcb(struct bufferevent *bev, short what, void *ctx);
105+
};
106+
107+
/****** Bitcoin specific TorController implementation ********/
108+
109+
/** Controller that connects to Tor control socket, authenticate, then create
110+
* and maintain an ephemeral onion service.
111+
*/
112+
class TorController
113+
{
114+
public:
115+
TorController(struct event_base* base, const std::string& tor_control_center, const CService& target);
116+
~TorController();
117+
118+
/** Get name of file to store private key in */
119+
fs::path GetPrivateKeyFile();
120+
121+
/** Reconnect, after getting disconnected */
122+
void Reconnect();
123+
private:
124+
struct event_base* base;
125+
const std::string m_tor_control_center;
126+
TorControlConnection conn;
127+
std::string private_key;
128+
std::string service_id;
129+
bool reconnect;
130+
struct event *reconnect_ev;
131+
float reconnect_timeout;
132+
CService service;
133+
const CService m_target;
134+
/** Cookie for SAFECOOKIE auth */
135+
std::vector<uint8_t> cookie;
136+
/** ClientNonce for SAFECOOKIE auth */
137+
std::vector<uint8_t> clientNonce;
138+
139+
/** Callback for ADD_ONION result */
140+
void add_onion_cb(TorControlConnection& conn, const TorControlReply& reply);
141+
/** Callback for AUTHENTICATE result */
142+
void auth_cb(TorControlConnection& conn, const TorControlReply& reply);
143+
/** Callback for AUTHCHALLENGE result */
144+
void authchallenge_cb(TorControlConnection& conn, const TorControlReply& reply);
145+
/** Callback for PROTOCOLINFO result */
146+
void protocolinfo_cb(TorControlConnection& conn, const TorControlReply& reply);
147+
/** Callback after successful connection */
148+
void connected_cb(TorControlConnection& conn);
149+
/** Callback after connection lost or failed connection attempt */
150+
void disconnected_cb(TorControlConnection& conn);
151+
152+
/** Callback for reconnect timer */
153+
static void reconnect_cb(evutil_socket_t fd, short what, void *arg);
154+
};
155+
24156
#endif /* BITCOIN_TORCONTROL_H */

0 commit comments

Comments
 (0)