|
@@ -10,10 +10,7 @@
|
|
|
from __future__ import print_function
|
|
|
from __future__ import with_statement
|
|
|
|
|
|
-
|
|
|
import cgitb
|
|
|
-cgitb.enable(format="plain")
|
|
|
-
|
|
|
import os
|
|
|
import signal
|
|
|
import subprocess
|
|
@@ -30,6 +27,9 @@ _BASE_ENVIRON = None
|
|
|
_TORRC_OPTIONS = None
|
|
|
_THE_NETWORK = None
|
|
|
|
|
|
+
|
|
|
+cgitb.enable(format="plain")
|
|
|
+
|
|
|
|
|
|
def mkdir_p(d, mode=511):
|
|
|
"""Create directory 'd' and all of its parents as needed. Unlike
|
|
@@ -244,15 +244,14 @@ class LocalNodeBuilder(NodeBuilder):
|
|
|
"--list-torrc-options",
|
|
|
"--hush"]
|
|
|
try:
|
|
|
- opts = subprocess.check_output(cmdline,
|
|
|
- bufsize=-1,
|
|
|
+ opts = subprocess.check_output(cmdline, bufsize=-1,
|
|
|
universal_newlines=True)
|
|
|
except OSError as e:
|
|
|
|
|
|
if e.errno == errno.ENOENT:
|
|
|
- print ("Cannot find tor binary %r. Use "
|
|
|
- "CHUTNEY_TOR environment variable to set the "
|
|
|
- "path, or put the binary into $PATH." % tor)
|
|
|
+ print("Cannot find tor binary %r. Use "
|
|
|
+ "CHUTNEY_TOR environment variable to set the "
|
|
|
+ "path, or put the binary into $PATH." % tor)
|
|
|
sys.exit(0)
|
|
|
else:
|
|
|
raise
|
|
@@ -278,15 +277,15 @@ class LocalNodeBuilder(NodeBuilder):
|
|
|
|
|
|
|
|
|
sline = line.strip()
|
|
|
- if (len(sline) == 0
|
|
|
- or sline[0] == '#'
|
|
|
- or sline.split()[0].lower() in lower_opts):
|
|
|
+ if (len(sline) == 0 or
|
|
|
+ sline[0] == '#' or
|
|
|
+ sline.split()[0].lower() in lower_opts):
|
|
|
f.writelines([line])
|
|
|
else:
|
|
|
|
|
|
|
|
|
|
|
|
- print (("The tor binary at %r does not support the "
|
|
|
+ print(("The tor binary at %r does not support the "
|
|
|
"option in the torrc line:\n"
|
|
|
"%r") % (tor, line.strip()))
|
|
|
|
|
@@ -341,11 +340,11 @@ class LocalNodeBuilder(NodeBuilder):
|
|
|
|
|
|
def _makeHiddenServiceDir(self):
|
|
|
"""Create the hidden service subdirectory for this node.
|
|
|
-
|
|
|
+
|
|
|
The directory name is stored under the 'hs_directory' environment
|
|
|
key. It is combined with the 'dir' data directory key to yield the
|
|
|
path to the hidden service directory.
|
|
|
-
|
|
|
+
|
|
|
448 is the decimal representation of the octal number 0700. Since
|
|
|
python2 only supports 0700 and python3 only supports 0o700, we can
|
|
|
use neither.
|
|
@@ -420,8 +419,8 @@ class LocalNodeBuilder(NodeBuilder):
|
|
|
stdout, stderr = p.communicate()
|
|
|
fingerprint = "".join((stdout.rstrip().split('\n')[-1]).split()[1:])
|
|
|
if not re.match(r'^[A-F0-9]{40}$', fingerprint):
|
|
|
- print (("Error when calling %r. It gave %r as a fingerprint "
|
|
|
- " and %r on stderr.")%(" ".join(cmdline), stdout, stderr))
|
|
|
+ print(("Error when calling %r. It gave %r as a fingerprint "
|
|
|
+ " and %r on stderr.") % (" ".join(cmdline), stdout, stderr))
|
|
|
sys.exit(1)
|
|
|
self._env['fingerprint'] = fingerprint
|
|
|
|
|
@@ -601,18 +600,18 @@ class LocalNodeController(NodeController):
|
|
|
sys.stdout.flush()
|
|
|
time.sleep(self._env['poll_launch_time'])
|
|
|
p.poll()
|
|
|
- if p.returncode != None and p.returncode != 0:
|
|
|
+ if p.returncode is not None and p.returncode != 0:
|
|
|
if self._env['poll_launch_time'] is None:
|
|
|
print("Couldn't launch %s (%s): %s" % (self._env['nick'],
|
|
|
" ".join(cmdline),
|
|
|
p.returncode))
|
|
|
else:
|
|
|
print("Couldn't poll %s (%s) "
|
|
|
- "after waiting %s seconds for launch"
|
|
|
- ": %s" % (self._env['nick'],
|
|
|
- " ".join(cmdline),
|
|
|
- self._env['poll_launch_time'],
|
|
|
- p.returncode))
|
|
|
+ "after waiting %s seconds for launch"
|
|
|
+ ": %s" % (self._env['nick'],
|
|
|
+ " ".join(cmdline),
|
|
|
+ self._env['poll_launch_time'],
|
|
|
+ p.returncode))
|
|
|
return False
|
|
|
return True
|
|
|
|
|
@@ -643,21 +642,22 @@ class LocalNodeController(NodeController):
|
|
|
if len(stline) > 0:
|
|
|
splline = stline.split()
|
|
|
|
|
|
- if (len(splline) > 0
|
|
|
- and splline[0].lower() == "RunAsDaemon".lower()
|
|
|
- and splline[1] == "1"):
|
|
|
+ if (len(splline) > 0 and
|
|
|
+ splline[0].lower() == "RunAsDaemon".lower() and
|
|
|
+ splline[1] == "1"):
|
|
|
|
|
|
|
|
|
runAsDaemon = True
|
|
|
if runAsDaemon:
|
|
|
|
|
|
self._env['poll_launch_time'] = None
|
|
|
- return True;
|
|
|
+ return True
|
|
|
else:
|
|
|
|
|
|
if self._env['poll_launch_time'] is None:
|
|
|
- self._env['poll_launch_time'] = self._env['poll_launch_time_default']
|
|
|
- return False;
|
|
|
+ self._env['poll_launch_time'] = \
|
|
|
+ self._env['poll_launch_time_default']
|
|
|
+ return False
|
|
|
|
|
|
DEFAULTS = {
|
|
|
'authority': False,
|
|
@@ -685,11 +685,11 @@ DEFAULTS = {
|
|
|
'authorities': "AlternateDirAuthority bleargh bad torrc file!",
|
|
|
'bridges': "Bridge bleargh bad torrc file!",
|
|
|
'core': True,
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
+
|
|
|
'poll_launch_time': None,
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
+
|
|
|
'poll_launch_time_default': 0.1,
|
|
|
|
|
|
'data_bytes': int(os.environ.get('CHUTNEY_DATA_BYTES', 10 * 1024)),
|
|
@@ -777,8 +777,7 @@ class TorEnviron(chutney.Templating.Environ):
|
|
|
if my['hs-hostname'] is None:
|
|
|
datadir = my['dir']
|
|
|
|
|
|
- hs_hostname_file = os.path.join(datadir,
|
|
|
- my['hs_directory'],
|
|
|
+ hs_hostname_file = os.path.join(datadir, my['hs_directory'],
|
|
|
'hostname')
|
|
|
try:
|
|
|
with open(hs_hostname_file, 'r') as hostnamefp:
|
|
@@ -787,8 +786,8 @@ class TorEnviron(chutney.Templating.Environ):
|
|
|
hostname = hostname.strip()
|
|
|
my['hs-hostname'] = hostname
|
|
|
except IOError as e:
|
|
|
- print("Error: hs %r error %d: %r opening hostname file '%r'"
|
|
|
- %(my['nick'], e.errno, e.strerror, hs_hostname_file))
|
|
|
+ print("Error: hs %r error %d: %r opening hostname file '%r'" %
|
|
|
+ (my['nick'], e.errno, e.strerror, hs_hostname_file))
|
|
|
return my['hs-hostname']
|
|
|
|
|
|
|
|
@@ -808,7 +807,7 @@ class Network(object):
|
|
|
self._nodes.append(n)
|
|
|
|
|
|
def move_aside_nodes(self):
|
|
|
- nodesdir = os.path.join(os.getcwd(),'net','nodes')
|
|
|
+ nodesdir = os.path.join(os.getcwd(), 'net', 'nodes')
|
|
|
|
|
|
if not os.path.exists(nodesdir):
|
|
|
return
|
|
@@ -817,9 +816,9 @@ class Network(object):
|
|
|
i = 0
|
|
|
while os.path.exists(newdir):
|
|
|
i += 1
|
|
|
- newdir = "%s.%d" %(newdirbase, i)
|
|
|
+ newdir = "%s.%d" % (newdirbase, i)
|
|
|
|
|
|
- print ("NOTE: renaming %r to %r"%(nodesdir, newdir))
|
|
|
+ print("NOTE: renaming %r to %r" % (nodesdir, newdir))
|
|
|
os.rename(nodesdir, newdir)
|
|
|
|
|
|
def _checkConfig(self):
|
|
@@ -876,7 +875,6 @@ class Network(object):
|
|
|
|
|
|
print("")
|
|
|
return rv
|
|
|
-
|
|
|
|
|
|
def hup(self):
|
|
|
print("Sending SIGHUP to nodes")
|
|
@@ -917,7 +915,7 @@ class Network(object):
|
|
|
def _verify_traffic(self):
|
|
|
"""Verify (parts of) the network by sending traffic through it
|
|
|
and verify what is received."""
|
|
|
- LISTEN_PORT = 4747
|
|
|
+ LISTEN_PORT = 4747
|
|
|
|
|
|
|
|
|
HS_PORT = 5858
|
|
@@ -927,8 +925,8 @@ class Network(object):
|
|
|
|
|
|
DATALEN = self._dfltEnv['data_bytes']
|
|
|
|
|
|
- DOTDATALEN = 5 * 1024 * 1024
|
|
|
- TIMEOUT = 3
|
|
|
+ DOTDATALEN = 5 * 1024 * 1024
|
|
|
+ TIMEOUT = 3
|
|
|
|
|
|
randomlen = self._calculate_randomlen(DATALEN)
|
|
|
reps = self._calculate_reps(DATALEN, randomlen)
|
|
@@ -948,10 +946,7 @@ class Network(object):
|
|
|
tmpdata = {}
|
|
|
|
|
|
bind_to = ('127.0.0.1', LISTEN_PORT)
|
|
|
- tt = chutney.Traffic.TrafficTester(bind_to,
|
|
|
- tmpdata,
|
|
|
- TIMEOUT,
|
|
|
- reps,
|
|
|
+ tt = chutney.Traffic.TrafficTester(bind_to, tmpdata, TIMEOUT, reps,
|
|
|
dot_reps)
|
|
|
client_list = filter(lambda n:
|
|
|
n._env['tag'] == 'c' or n._env['tag'] == 'bc',
|
|
@@ -975,15 +970,12 @@ class Network(object):
|
|
|
|
|
|
|
|
|
total_path_node_count = 0
|
|
|
- total_path_node_count += self._configure_exits(tt, bind_to,
|
|
|
- tmpdata, reps,
|
|
|
- client_list, exit_list,
|
|
|
- LISTEN_PORT)
|
|
|
- total_path_node_count += self._configure_hs(tt,
|
|
|
- tmpdata, reps,
|
|
|
+ total_path_node_count += self._configure_exits(tt, bind_to, tmpdata,
|
|
|
+ reps, client_list,
|
|
|
+ exit_list, LISTEN_PORT)
|
|
|
+ total_path_node_count += self._configure_hs(tt, tmpdata, reps,
|
|
|
client_list, hs_list,
|
|
|
- HS_PORT,
|
|
|
- LISTEN_PORT)
|
|
|
+ HS_PORT, LISTEN_PORT)
|
|
|
print("Transmitting Data:")
|
|
|
start_time = time.clock()
|
|
|
status = tt.run()
|
|
@@ -1020,27 +1012,22 @@ class Network(object):
|
|
|
|
|
|
|
|
|
|
|
|
- def _configure_exits(self, tt, bind_to,
|
|
|
- tmpdata, reps,
|
|
|
- client_list, exit_list,
|
|
|
- LISTEN_PORT):
|
|
|
+ def _configure_exits(self, tt, bind_to, tmpdata, reps, client_list,
|
|
|
+ exit_list, LISTEN_PORT):
|
|
|
CLIENT_EXIT_PATH_NODES = 4
|
|
|
connection_count = self._dfltEnv['connection_count']
|
|
|
exit_path_node_count = 0
|
|
|
if len(exit_list) > 0:
|
|
|
- exit_path_node_count += (len(client_list)
|
|
|
- * CLIENT_EXIT_PATH_NODES
|
|
|
- * connection_count)
|
|
|
+ exit_path_node_count += (len(client_list) *
|
|
|
+ CLIENT_EXIT_PATH_NODES *
|
|
|
+ connection_count)
|
|
|
for op in client_list:
|
|
|
print(" Exit to %s:%d via client %s:%s"
|
|
|
% ('127.0.0.1', LISTEN_PORT,
|
|
|
'localhost', op._env['socksport']))
|
|
|
for i in range(connection_count):
|
|
|
- tt.add(chutney.Traffic.Source(tt,
|
|
|
- bind_to,
|
|
|
- tmpdata,
|
|
|
- ('localhost',
|
|
|
- int(op._env['socksport'])),
|
|
|
+ proxy = ('localhost', int(op._env['socksport']))
|
|
|
+ tt.add(chutney.Traffic.Source(tt, bind_to, tmpdata, proxy,
|
|
|
reps))
|
|
|
return exit_path_node_count
|
|
|
|
|
@@ -1050,16 +1037,12 @@ class Network(object):
|
|
|
|
|
|
|
|
|
|
|
|
- def _configure_hs(self, tt,
|
|
|
- tmpdata, reps,
|
|
|
- client_list, hs_list,
|
|
|
- HS_PORT,
|
|
|
+ def _configure_hs(self, tt, tmpdata, reps, client_list, hs_list, HS_PORT,
|
|
|
LISTEN_PORT):
|
|
|
CLIENT_HS_PATH_NODES = 8
|
|
|
connection_count = self._dfltEnv['connection_count']
|
|
|
- hs_path_node_count = (len(hs_list)
|
|
|
- * CLIENT_HS_PATH_NODES
|
|
|
- * connection_count)
|
|
|
+ hs_path_node_count = (len(hs_list) * CLIENT_HS_PATH_NODES *
|
|
|
+ connection_count)
|
|
|
|
|
|
if self._dfltEnv['hs_multi_client']:
|
|
|
hs_client_list = client_list
|
|
@@ -1073,15 +1056,12 @@ class Network(object):
|
|
|
for client in hs_client_list:
|
|
|
print(" HS to %s:%d (%s:%d) via client %s:%s"
|
|
|
% (hs._env['hs_hostname'], HS_PORT,
|
|
|
- '127.0.0.1', LISTEN_PORT,
|
|
|
- 'localhost', client._env['socksport']))
|
|
|
+ '127.0.0.1', LISTEN_PORT,
|
|
|
+ 'localhost', client._env['socksport']))
|
|
|
for i in range(connection_count):
|
|
|
- tt.add(chutney.Traffic.Source(tt,
|
|
|
- hs_bind_to,
|
|
|
- tmpdata,
|
|
|
- ('localhost',
|
|
|
- int(client._env['socksport'])),
|
|
|
- reps))
|
|
|
+ proxy = ('localhost', int(client._env['socksport']))
|
|
|
+ tt.add(chutney.Traffic.Source(tt, hs_bind_to, tmpdata,
|
|
|
+ proxy, reps))
|
|
|
return hs_path_node_count
|
|
|
|
|
|
|
|
@@ -1098,20 +1078,17 @@ class Network(object):
|
|
|
start_time, end_time):
|
|
|
|
|
|
|
|
|
- MIN_BWDATA = 5 * 1024 * 1024
|
|
|
- MIN_ELAPSED_TIME = 1.0
|
|
|
+ MIN_BWDATA = 5 * 1024 * 1024
|
|
|
+ MIN_ELAPSED_TIME = 1.0
|
|
|
cumulative_data_sent = total_path_node_count * data_length
|
|
|
elapsed_time = end_time - start_time
|
|
|
- if (cumulative_data_sent >= MIN_BWDATA
|
|
|
- and elapsed_time >= MIN_ELAPSED_TIME):
|
|
|
+ if (cumulative_data_sent >= MIN_BWDATA and
|
|
|
+ elapsed_time >= MIN_ELAPSED_TIME):
|
|
|
|
|
|
BWDIVISOR = 1024*1024
|
|
|
- single_stream_bandwidth = (data_length
|
|
|
- / elapsed_time
|
|
|
- / BWDIVISOR)
|
|
|
- overall_bandwidth = (cumulative_data_sent
|
|
|
- / elapsed_time
|
|
|
- / BWDIVISOR)
|
|
|
+ single_stream_bandwidth = (data_length / elapsed_time / BWDIVISOR)
|
|
|
+ overall_bandwidth = (cumulative_data_sent / elapsed_time /
|
|
|
+ BWDIVISOR)
|
|
|
print("Single Stream Bandwidth: %.2f MBytes/s"
|
|
|
% single_stream_bandwidth)
|
|
|
print("Overall tor Bandwidth: %.2f MBytes/s"
|
|
@@ -1135,10 +1112,11 @@ def usage(network):
|
|
|
|
|
|
|
|
|
def exit_on_error(err_msg):
|
|
|
- print ("Error: {0}\n".format(err_msg))
|
|
|
- print (usage(_THE_NETWORK))
|
|
|
+ print("Error: {0}\n".format(err_msg))
|
|
|
+ print(usage(_THE_NETWORK))
|
|
|
sys.exit(1)
|
|
|
|
|
|
+
|
|
|
def runConfigFile(verb, data):
|
|
|
_GLOBALS = dict(_BASE_ENVIRON=_BASE_ENVIRON,
|
|
|
Node=Node,
|
|
@@ -1163,6 +1141,7 @@ def parseArgs():
|
|
|
exit_on_error("Cannot find networkfile: {0}.".format(sys.argv[2]))
|
|
|
return {'network_cfg': sys.argv[2], 'action': sys.argv[1]}
|
|
|
|
|
|
+
|
|
|
def main():
|
|
|
global _BASE_ENVIRON
|
|
|
global _TORRC_OPTIONS
|