1 # Future imports for Python 2.7, mandatory in 3.0
2 from __future__
import division
3 from __future__
import print_function
4 from __future__
import unicode_literals
23 logging
.warning('SKIP: {}'.format(msg
))
26 def try_connecting_to_socksport():
27 socks_socket
= socket
.socket(socket
.AF_INET
, socket
.SOCK_STREAM
)
28 e
= socks_socket
.connect_ex(('127.0.0.1', socks_port
))
30 tor_process
.terminate()
31 fail('Cannot connect to SOCKSPort: error ' + os
.strerror(e
))
35 cutoff
= time
.time() + LOG_TIMEOUT
36 while time
.time() < cutoff
:
37 l
= tor_process
.stdout
.readline()
38 l
= l
.decode('utf8', 'backslashreplace')
40 logging
.info('Tor logged: "{}"'.format(l
.strip()))
42 # readline() returns a blank string when there is no output
45 logging
.debug('Tor has not logged anything, waiting for "{}"'.format(s
))
48 logging
.info('Tor logged: "{}", waiting for "{}"'.format(l
.strip(), s
))
49 fail('Could not find "{}" in logs after {} seconds'.format(s
, LOG_TIMEOUT
))
51 def pick_random_port():
56 port
= random
.randint(10000, 60000)
57 s
= socket
.socket(socket
.AF_INET
, socket
.SOCK_STREAM
)
58 if s
.connect_ex(('127.0.0.1', port
)) == 0:
64 fail('Could not find a random free port between 10000 and 60000')
68 logging
.basicConfig(level
=logging
.DEBUG
,
69 format
='%(asctime)s.%(msecs)03d %(message)s',
70 datefmt
='%Y-%m-%d %H:%M:%S')
72 if sys
.hexversion
< 0x02070000:
73 fail("ERROR: unsupported Python version (should be >= 2.7)")
75 if sys
.hexversion
> 0x03000000 and sys
.hexversion
< 0x03010000:
76 fail("ERROR: unsupported Python3 version (should be >= 3.1)")
78 if 'TOR_SKIP_TEST_REBIND' in os
.environ
:
79 skip('$TOR_SKIP_TEST_REBIND is set')
81 control_port
= pick_random_port()
82 socks_port
= pick_random_port()
84 assert control_port
!= 0
85 assert socks_port
!= 0
88 fail('Usage: %s <path-to-tor> <data-dir>' % sys
.argv
[0])
90 if not os
.path
.exists(sys
.argv
[1]):
91 fail('ERROR: cannot find tor at %s' % sys
.argv
[1])
92 if not os
.path
.exists(sys
.argv
[2]):
93 fail('ERROR: cannot find datadir at %s' % sys
.argv
[2])
95 tor_path
= sys
.argv
[1]
96 data_dir
= sys
.argv
[2]
98 empty_torrc_path
= os
.path
.join(data_dir
, 'empty_torrc')
99 open(empty_torrc_path
, 'w').close()
100 empty_defaults_torrc_path
= os
.path
.join(data_dir
, 'empty_defaults_torrc')
101 open(empty_defaults_torrc_path
, 'w').close()
103 tor_process
= subprocess
.Popen([tor_path
,
104 '-DataDirectory', data_dir
,
105 '-ControlPort', '127.0.0.1:{}'.format(control_port
),
106 '-SOCKSPort', '127.0.0.1:{}'.format(socks_port
),
107 '-Log', 'debug stdout',
108 '-LogTimeGranularity', '1',
109 '-FetchServerDescriptors', '0',
110 '-f', empty_torrc_path
,
111 '--defaults-torrc', empty_defaults_torrc_path
,
113 stdout
=subprocess
.PIPE
,
114 stderr
=subprocess
.PIPE
)
116 if tor_process
== None:
117 fail('ERROR: running tor failed')
119 wait_for_log('Opened Control listener')
121 try_connecting_to_socksport()
123 control_socket
= socket
.socket(socket
.AF_INET
, socket
.SOCK_STREAM
)
124 if control_socket
.connect_ex(('127.0.0.1', control_port
)):
125 tor_process
.terminate()
126 fail('Cannot connect to ControlPort')
128 control_socket
.sendall('AUTHENTICATE \r\n'.encode('ascii'))
129 control_socket
.sendall('SETCONF SOCKSPort=0.0.0.0:{}\r\n'.format(socks_port
).encode('ascii'))
130 wait_for_log('Opened Socks listener')
132 try_connecting_to_socksport()
134 control_socket
.sendall('SETCONF SOCKSPort=127.0.0.1:{}\r\n'.format(socks_port
).encode('ascii'))
135 wait_for_log('Opened Socks listener')
137 try_connecting_to_socksport()
139 control_socket
.sendall('SIGNAL HALT\r\n'.encode('ascii'))
141 wait_for_log('exiting cleanly')
145 tor_process
.terminate()
147 if e
.errno
== errno
.ESRCH
: # errno 3: No such process
148 # assume tor has already exited due to SIGNAL HALT
149 logging
.warn("Tor has already exited")