11import sys
2- import itertools
32
4- from twisted .internet import defer , reactor
3+ from twisted .internet import defer , reactor , endpoints
54from txtorcon .interface import CircuitListenerMixin , IStreamAttacher , StreamListenerMixin
6- from txtorcon import TorState , launch_tor , build_tor_connection , TorConfig
5+ import txtorcon
6+ from txtorcon import TorState , launch_tor
77from txtorcon .util import available_tcp_port
88from zope .interface import implementer
99
@@ -134,16 +134,6 @@ def launch_and_get_state(ignore):
134134 return get_random_tor_ports ().addCallback (launch_and_get_state )
135135
136136
137- def update_tor_config (tor , config ):
138- """
139- Update the Tor config from a dict of config key: value pairs.
140- """
141- config_pairs = [(key , value ) for key , value in config .items ()]
142- d = tor .protocol .set_conf (* itertools .chain .from_iterable (config_pairs ))
143- d .addCallback (lambda ok : ok )
144- return d .addCallback (lambda result : tor )
145-
146-
147137def setconf_singleport_exit (tor ):
148138 port = available_tcp_port (reactor )
149139
@@ -159,6 +149,7 @@ def add_single_port_exit(port):
159149 lambda ign : tor .routers [tor .protocol .get_info ("fingerprint" )])
160150
161151
152+ @defer .inlineCallbacks
162153def connect_to_tor (launch_tor , circuit_build_timeout , circuit_idle_timeout , control_port = 9051 ):
163154 """
164155 Launch or connect to a Tor instance
@@ -179,17 +170,23 @@ def connect_to_tor(launch_tor, circuit_build_timeout, circuit_idle_timeout, cont
179170
180171 if launch_tor :
181172 log .info ("Spawning a new Tor instance." )
182- c = TorConfig ()
183- # Update Tor config before launching a new Tor.
184- c .config .update (tor_options )
185- tor = start_tor (c )
186-
173+ # TODO: Pass in data_dir directory so consensus can be cached
174+ tor = yield txtorcon .launch (reactor )
187175 else :
188176 log .info ("Trying to connect to a running Tor instance." )
189- tor = build_tor_connection ((reactor , '127.0.0.1' , control_port ,))
190- # Update the Tor config on a running Tor.
191- tor .addCallback (update_tor_config , tor_options )
192-
193- tor .addErrback (log .debug )
194-
195- return tor
177+ tor = yield txtorcon .connect (
178+ reactor ,
179+ endpoints .TCP4ClientEndpoint (reactor , "localhost" , control_port )
180+ )
181+
182+ # Get Tor state first to avoid a race conditions where CONF_CHANGED
183+ # messages are received while Txtorcon is reading the consensus.
184+ tor_state = yield tor .create_state ()
185+
186+ # Update Tor config options from dictionary
187+ tor_config = yield tor .get_config ()
188+ for key , value in tor_options .items ():
189+ setattr (tor_config , key , value )
190+ yield tor_config .save () # Send updated options to Tor
191+
192+ defer .returnValue (tor_state )
0 commit comments