commit c0cad1259227019150258b5dfc2bc8d4844590a1 Author: Arturo Filastò art@fuffa.org Date: Wed Apr 30 14:57:15 2014 +0200
Refactoring and tidying up of various different parts of the codebase.
Let pylint guide the way! --- oonib/bouncer/handlers.py | 17 ++-- oonib/config.py | 11 ++- oonib/daphn3.py | 4 +- oonib/deck/api.py | 4 +- oonib/deck/handlers.py | 10 ++- oonib/errors.py | 50 ++++++++++-- oonib/handlers.py | 4 + oonib/input/api.py | 4 +- oonib/input/handlers.py | 21 +++-- oonib/log.py | 4 +- oonib/options.py | 14 ++-- oonib/otime.py | 24 ++++-- oonib/policy/handlers.py | 7 +- oonib/report/handlers.py | 155 +++++++++++++++++++------------------ oonib/runner.py | 27 ++++--- oonib/testhelpers/dns_helpers.py | 17 ++-- oonib/testhelpers/http_helpers.py | 9 ++- oonib/testhelpers/ssl_helpers.py | 2 +- oonib/testhelpers/tcp_helpers.py | 11 ++- 19 files changed, 225 insertions(+), 170 deletions(-)
diff --git a/oonib/bouncer/handlers.py b/oonib/bouncer/handlers.py index 0a5b51f..81d13f3 100644 --- a/oonib/bouncer/handlers.py +++ b/oonib/bouncer/handlers.py @@ -1,10 +1,11 @@ -import json +import json import random import yaml from oonib import errors as e from oonib.handlers import OONIBHandler from oonib.config import config
+ class Bouncer(object): def __init__(self): with open(config.main.bouncer_file) as f: @@ -20,7 +21,7 @@ class Bouncer(object): for collectorName, helpers in bouncerFile['collector'].items(): if collectorName not in self.knownCollectors: self.knownCollectors.append(collectorName) - + def updateKnownHelpers(self, bouncerFile): self.knownHelpers = {} for collectorName, helpers in bouncerFile['collector'].items(): @@ -47,13 +48,13 @@ class Bouncer(object): helpers = self.knownHelpers[helper_name] except KeyError: raise e.TestHelperNotFound - + helpers_dict = {} for helper in helpers: helpers_dict[helper['collector-name']] = helper['helper-address']
return helpers_dict - + def filterHelperAddresses(self, requested_helpers): """ Returns a dict of collectors that support all the requested_helpers. @@ -79,7 +80,7 @@ class Bouncer(object): } }
- or + or
{'error': 'test-helper-not-found'}
@@ -105,9 +106,11 @@ class Bouncer(object): response = {'error': 'test-helper-not-found'} return response
- response['default'] = {'collector': random.choice(self.knownCollectors)} + response['default'] = {'collector': + random.choice(self.knownCollectors)} return response
+ class BouncerQueryHandler(OONIBHandler): def initialize(self): self.bouncer = Bouncer() @@ -122,7 +125,7 @@ class BouncerQueryHandler(OONIBHandler): requested_helpers = query['test-helpers'] except KeyError: raise e.TestHelpersKeyMissing - + if not isinstance(requested_helpers, list): raise e.InvalidRequest
diff --git a/oonib/config.py b/oonib/config.py index 1388e6b..31128a9 100644 --- a/oonib/config.py +++ b/oonib/config.py @@ -6,17 +6,16 @@ from oonib import __version__ from oonib.options import OONIBOptions import os
+ class Config(object): - main = None - helpers = None + main = {} + helpers = {} reports = {} backend_version = __version__ opts = OONIBOptions()
- def __init__(self): - self.opts.parseOptions() - def load(self): + self.opts.parseOptions() try: config_file = self.opts['config'] except KeyError: @@ -35,7 +34,7 @@ class Config(object): self.helpers[name] = Storage(helper.items())
self.check_paths() - + def check_paths(self): def check_path(directory, complaint): if not (directory and os.path.isdir(directory)): diff --git a/oonib/daphn3.py b/oonib/daphn3.py index 9c5f290..4b4eac4 100644 --- a/oonib/daphn3.py +++ b/oonib/daphn3.py @@ -96,7 +96,7 @@ def daphn3Mutate(steps, step_idx, mutation_idx): if idx == step_idx: step_string = step.values()[0] step_key = step.keys()[0] - mutated_string = daphn3MutateString(step_string, + mutated_string = daphn3MutateString(step_string, mutation_idx) mutated_steps.append({step_key: mutated_string}) else: @@ -121,7 +121,7 @@ class Daphn3Protocol(protocol.Protocol): def _current_step_data(self): step_idx, mutation_idx = self.factory.mutation log.debug("Mutating %s %s" % (step_idx, mutation_idx)) - mutated_step = daphn3Mutate(self.steps, + mutated_step = daphn3Mutate(self.steps, step_idx, mutation_idx) log.debug("Mutated packet into %s" % mutated_step) return mutated_step[self.current_step].values()[0] diff --git a/oonib/deck/api.py b/oonib/deck/api.py index a2f1164..1c19d32 100644 --- a/oonib/deck/api.py +++ b/oonib/deck/api.py @@ -5,6 +5,6 @@ from oonib.config import config deckAPI = [ (r"/deck", handlers.DeckListHandler), (r"/deck/([a-z0-9]{64})$", handlers.DeckDescHandler), - (r"/deck/([a-z0-9]{64})/file$", web.StaticFileHandler, {"path": - config.main.deck_dir}), + (r"/deck/([a-z0-9]{64})/file$", web.StaticFileHandler, + {"path": config.main.deck_dir}), ] diff --git a/oonib/deck/handlers.py b/oonib/deck/handlers.py index b9589b0..ca17e95 100644 --- a/oonib/deck/handlers.py +++ b/oonib/deck/handlers.py @@ -1,5 +1,4 @@ import glob -import json import os import re import yaml @@ -9,6 +8,7 @@ from oonib.handlers import OONIBHandler from oonib import log from oonib.config import config
+ class DeckDescHandler(OONIBHandler): def get(self, deckID): # note: @@ -32,18 +32,20 @@ class DeckDescHandler(OONIBHandler): raise e.MissingDeckKeys self.write(response)
+ class DeckListHandler(OONIBHandler): def get(self): - if not config.main.deck_dir: + if not config.main.deck_dir: self.set_status(501) raise e.NoDecksConfigured
path = os.path.abspath(config.main.deck_dir) + "/*" decknames = map(os.path.basename, glob.iglob(path)) - decknames = filter(lambda y: re.match("[a-z0-9]{64}.desc", y), decknames) + decknames = filter(lambda y: re.match("[a-z0-9]{64}.desc", y), + decknames) deckList = [] for deckname in decknames: - with open(os.path.join(config.main.deck_dir, deckname)) as f: + with open(os.path.join(config.main.deck_dir, deckname)) as f: d = yaml.safe_load(f) deckList.append({ 'id': deckname, diff --git a/oonib/errors.py b/oonib/errors.py index 6f768d0..3f1167a 100644 --- a/oonib/errors.py +++ b/oonib/errors.py @@ -1,87 +1,125 @@ from cyclone.web import HTTPError
+ class OONIBError(HTTPError): status_code = 500 log_message = 'oonib-error' + def __init__(self): pass
+ class InvalidRequest(OONIBError): status_code = 400 log_message = 'invalid-request'
+ class NoHelperFound(OONIBError): status_code = 404 log_message = 'no-helper-found'
+ class InvalidInputHash(OONIBError): status_code = 406 log_message = 'invalid-input-hash'
+ class InvalidNettestName(OONIBError): status_code = 406 log_message = 'invalid-nettest-name'
+ class InputHashNotProvided(OONIBError): status_code = 406 log_message = 'input-hash-not-provided'
+ +class InputDescriptorNotFound(OONIBError): + status_code = 404 + log_message = 'input-descriptor-not-found' + + class InvalidRequestField(OONIBError): def __init__(self, field_name): self.status_code = 400 self.log_message = "invalid-request-field %s" % field_name
+ class MissingRequestField(OONIBError): def __init__(self, field_name): self.status_code = 400 self.log_message = "missing-request-field %s" % field_name
+ class MissingReportHeaderKey(OONIBError): def __init__(self, key): self.status_code = 406 self.log_message = "missing-report-header-key %s" % key
+ class MissingDeckKeys(OONIBError): status_code = 400 log_message = "missing-deck-keys"
+ class MissingDeck(OONIBError): status_code = 400 log_message = "missing-deck"
+ class NoDecksConfigured(OONIBError): status_code = 501 log_message = "no-decks-configured"
+ class InvalidReportHeader(OONIBError): def __init__(self, key): self.status_code = 406 self.log_message = "invalid-report-header %s" % key
+ class ReportNotFound(OONIBError): status_code = 404 log_message = "report-not-found"
+ class NoValidCollector(OONIBError): pass
+ class TestHelpersKeyMissing(OONIBError): status_code = 400 log_message = "test-helpers-key-missing"
+ class TestHelperNotFound(OONIBError): status_code = 404 log_message = "test-helper-not-found"
-class ConfigFileNotSpecified(Exception): pass
-class ConfigFileDoesNotExist(Exception): pass +class ConfigFileNotSpecified(Exception): + pass
-class InvalidReportDirectory(Exception): pass
-class InvalidArchiveDirectory(Exception): pass +class ConfigFileDoesNotExist(Exception): + pass
-class InvalidInputDirectory(Exception): pass
-class InvalidDeckDirectory(Exception): pass +class InvalidReportDirectory(Exception): + pass + + +class InvalidArchiveDirectory(Exception): + pass
+ +class InvalidInputDirectory(Exception): + pass + + +class InvalidDeckDirectory(Exception): + pass + + +class InvalidTimestampFormat(Exception): + pass diff --git a/oonib/handlers.py b/oonib/handlers.py index 20c831b..f92d684 100644 --- a/oonib/handlers.py +++ b/oonib/handlers.py @@ -3,12 +3,16 @@ import types from cyclone import escape from cyclone import web
+from oonib import log + + class OONIBHandler(web.RequestHandler): def write_error(self, status_code, exception=None, **kw): self.set_status(status_code) if hasattr(exception, 'log_message'): self.write({'error': exception.log_message}) else: + log.error(exception) self.write({'error': 'error'})
def write(self, chunk): diff --git a/oonib/input/api.py b/oonib/input/api.py index 811da29..32ecd10 100644 --- a/oonib/input/api.py +++ b/oonib/input/api.py @@ -5,6 +5,6 @@ from oonib.config import config inputAPI = [ (r"/input", handlers.InputListHandler), (r"/input/([a-f0-9]{64})", handlers.InputDescHandler), - (r"/input/([a-f0-9]{64})/file$", web.StaticFileHandler, {"path": - config.main.input_dir}), + (r"/input/([a-f0-9]{64})/file$", web.StaticFileHandler, + {"path": config.main.input_dir}), ] diff --git a/oonib/input/handlers.py b/oonib/input/handlers.py index 33bec55..53501fa 100644 --- a/oonib/input/handlers.py +++ b/oonib/input/handlers.py @@ -1,38 +1,35 @@ import glob -import json import os import yaml
from oonib.handlers import OONIBHandler from oonib import log +from oonib import errors as e from oonib.config import config
+ class InputDescHandler(OONIBHandler): def get(self, inputID): bn = os.path.basename(inputID) + ".desc" try: f = open(os.path.join(config.main.input_dir, bn)) except IOError: - log.err("No Input Descriptor found for id %s" % inputID) - self.set_status(404) - self.write({'error': 'missing-input'}) - return + log.err("No Input Descriptor found for id %s" % inputID) + raise e.InputDescriptorNotFound with f: inputDesc = yaml.safe_load(f) - + response = {'id': inputID} for k in ['name', 'description', 'version', 'author', 'date']: try: response[k] = inputDesc[k] - except Exception, e: # XXX this should probably be KeyError - log.exception(e) - log.err("Invalid Input Descriptor found for id %s" % inputID) - self.set_status(500) - self.write({'error': 'invalid-input-descriptor'}) - return + except KeyError: + log.err("Invalid Input Descriptor found for id %s" % inputID) + raise e.InputDescriptorNotFound
self.write(response)
+ class InputListHandler(OONIBHandler): def get(self): path = os.path.abspath(config.main.input_dir) + "/*.desc" diff --git a/oonib/log.py b/oonib/log.py index 7a6e4cb..36fe414 100644 --- a/oonib/log.py +++ b/oonib/log.py @@ -87,8 +87,8 @@ def msg(msg, *arg, **kw):
def debug(msg, *arg, **kw): - if config.main.debug: - print "[D] %s" % log_encode(msg) + if config.main.get('debug'): + print "[D] %s" % msg
def warn(msg, *arg, **kw): diff --git a/oonib/options.py b/oonib/options.py index d5c87b3..9abb355 100644 --- a/oonib/options.py +++ b/oonib/options.py @@ -1,14 +1,12 @@ from twisted.python import usage -from twisted.python.runtime import platformType
-if platformType == "win32": - from twisted.scripts._twistw import ServerOptions -else: - from twisted.scripts._twistd_unix import ServerOptions
class OONIBOptions(usage.Options): - synopsis = """%s [options] [path to test].py """ + synopsis = """%s [options]""" + + longdesc = ("oonib provides the backend component of ooni-probe." + "oonib provides test helper services and a reporting " + "backend service. oonib is intended to be run as a " + "daemon and most options are set in its configuration file")
- longdesc = ("oonib provides the backend component of ooni-probe. oonib provides test helper services and a reporting backend service. oonib is intended to be run as a daemon and most options are set in its configuration file") - optParameters = [["config", "c", "oonib.conf", "Path to config file"]] diff --git a/oonib/otime.py b/oonib/otime.py index e38089b..67a6bc6 100644 --- a/oonib/otime.py +++ b/oonib/otime.py @@ -1,41 +1,46 @@ import time +from oonib import errors as e from datetime import datetime
+ def utcDateNow(): """ Returns the datetime object of the current UTC time. """ return datetime.utcnow()
+ def utcTimeNow(): """ Returns seconds since epoch in UTC time, it's of type float. """ return time.mktime(time.gmtime())
+ def dateToTime(date): """ Takes as input a datetime object and outputs the seconds since epoch. """ return time.mktime(date.timetuple())
+ def prettyDateNow(): """ Returns a good looking string for the local time. """ return datetime.now().ctime()
+ def utcPrettyDateNow(): """ Returns a good looking string for utc time. """ return datetime.utcnow().ctime()
+ def timeToPrettyDate(time_val): return time.ctime(time_val)
-class InvalidTimestampFormat(Exception): - pass
def fromTimestamp(s): """ @@ -47,17 +52,23 @@ def fromTimestamp(s): ex. 1912-06-23T101234Z"
Note: we currently only support parsing strings that are generated from the - timestamp function and have no intention in supporting the full standard. + timestamp function and have no intention in supporting the full + standard. """ try: date_part, time_part = s.split('T') hours, minutes, seconds = time_part[:2], time_part[2:4], time_part[4:6] year, month, day = date_part.split('-') except: - raise InvalidTimestampFormat(s) + raise e.InvalidTimestampFormat(s) + + return datetime(int(year), + int(month), + int(day), + int(hours), + int(minutes), + int(seconds))
- return datetime(int(year), int(month), int(day), int(hours), int(minutes), - int(seconds))
def timestamp(t=None): """ @@ -86,4 +97,3 @@ def timestamp(t=None): t = datetime.utcnow() ISO8601 = "%Y-%m-%dT%H%M%SZ" return t.strftime(ISO8601) - diff --git a/oonib/policy/handlers.py b/oonib/policy/handlers.py index cbf1c08..e81dd21 100644 --- a/oonib/policy/handlers.py +++ b/oonib/policy/handlers.py @@ -1,5 +1,3 @@ -import json -import os import yaml
from oonib import errors as e @@ -7,6 +5,7 @@ from oonib.handlers import OONIBHandler
from oonib.config import config
+ class Policy(object): nettest = None input = None @@ -38,10 +37,12 @@ class Policy(object): if not any(nt['name'] == nettest_name for nt in self.nettest): raise e.InvalidNettestName
+ class PolicyHandler(OONIBHandler): def initialize(self): self.policy = Policy()
+ class NetTestPolicyHandler(PolicyHandler): def get(self): """ @@ -49,10 +50,10 @@ class NetTestPolicyHandler(PolicyHandler): """ self.write(self.policy.nettest)
+ class InputPolicyHandler(PolicyHandler): def get(self): """ return list of input ids """ self.write(self.policy.input) - diff --git a/oonib/report/handlers.py b/oonib/report/handlers.py index 34aa8d9..01a665a 100644 --- a/oonib/report/handlers.py +++ b/oonib/report/handlers.py @@ -1,5 +1,3 @@ -import random -import string import time import yaml import json @@ -16,35 +14,48 @@ from datetime import datetime from oonib import randomStr, otime, log from oonib.config import config
-class MissingField(Exception): - pass
-class InvalidRequestField(Exception): - pass +def report_file_name(report_details): + timestamp = otime.timestamp(datetime.fromtimestamp(report_details['start_time'])) + dst_filename = '{test_name}-{timestamp}-{probe_asn}-probe.yamloo'.format( + timestamp=timestamp, + **report_details) + return dst_filename
class Report(object): - def __init__(self, report_id): + delayed_call = None + + def __init__(self, report_id, + stale_time, + report_dir, + archive_dir, + reports): self.report_id = report_id - self.delayed_call = None + + self.stale_time = stale_time + self.report_dir = report_dir + self.archive_dir = archive_dir + self.reports = reports
self.refresh() - + def refresh(self): self.last_updated = time.time() if self.delayed_call: self.delayed_call.cancel() - self.delayed_call = reactor.callLater(config.main.stale_time, self.stale_check) + self.delayed_call = reactor.callLater(self.stale_time, + self.stale_check)
def stale_check(self): - if (time.time() - self.last_updated) > config.main.stale_time: + if (time.time() - self.last_updated) > self.stale_time: try: self.close() - except ReportNotFound: + except e.ReportNotFound: pass
def close(self): def get_report_path(report_id): - return os.path.join(config.main.report_dir, report_id) + return os.path.join(self.report_dir, report_id)
report_filename = get_report_path(self.report_id) try: @@ -52,14 +63,10 @@ class Report(object): g = yaml.safe_load_all(fd) report_details = g.next() except IOError: - raise ReportNotFound - - timestamp = otime.timestamp(datetime.fromtimestamp(report_details['start_time'])) - dst_filename = '{test_name}-{timestamp}-{probe_asn}-probe.yamloo'.format( - timestamp=timestamp, - **report_details) + raise e.ReportNotFound
- dst_path = os.path.join(config.main.archive_dir, + dst_filename = report_file_name(report_details) + dst_path = os.path.join(self.archive_dir, report_details['probe_cc'])
if not os.path.isdir(dst_path): @@ -68,7 +75,8 @@ class Report(object): dst_path = os.path.join(dst_path, dst_filename) os.rename(report_filename, dst_path)
- del config.reports[self.report_id] + self.delayed_call.cancel() + del self.reports[self.report_id]
def parseUpdateReportRequest(request): #db_report_id_regexp = re.compile("[a-zA-Z0-9]+$") @@ -85,10 +93,10 @@ def parseUpdateReportRequest(request): try: report_id = parsed_request['report_id'] except KeyError: - raise MissingField('report_id') + raise e.MissingField('report_id')
if not re.match(report_id_regexp, report_id): - raise InvalidRequestField('report_id') + raise e.InvalidRequestField('report_id')
return parsed_request
@@ -117,79 +125,82 @@ def parseNewReportRequest(request): try: value_to_check = parsed_request[k] except KeyError: - raise MissingField(k) + raise e.MissingField(k)
print "Matching %s with %s | %s" % (regexp, value_to_check, k) if re.match(regexp, str(value_to_check)): continue else: - raise InvalidRequestField(k) - + raise e.InvalidRequestField(k) + try: requested_test_helper = parsed_request['test_helper'] if not re.match(test_helper, str(requested_test_helper)): - raise InvalidRequestField('test_helper') + raise e.InvalidRequestField('test_helper') except KeyError: pass
return parsed_request
-class InvalidReportHeader(Exception): - pass - -class MissingReportHeaderKey(InvalidReportHeader): - pass - def validate_report_header(report_header): required_keys = ['probe_asn', 'probe_cc', 'probe_ip', 'software_name', 'software_version', 'test_name', 'test_version'] for key in required_keys: if key not in report_header: - raise MissingReportHeaderKey(key) + raise e.MissingReportHeaderKey(key)
if report_header['probe_asn'] is None: report_header['probe_asn'] = 'AS0'
if not re.match('AS[0-9]+$', report_header['probe_asn']): - raise InvalidReportHeader('probe_asn') + raise e.InvalidReportHeader('probe_asn')
# If no country is known, set it to be ZZ (user assigned value in ISO 3166) if report_header['probe_cc'] is None: report_header['probe_cc'] = 'ZZ'
if not re.match('[a-zA-Z]{2}$', report_header['probe_cc']): - raise InvalidReportHeader('probe_cc') + raise e.InvalidReportHeader('probe_cc')
if not re.match('[a-z_-]+$', report_header['test_name']): - raise InvalidReportHeader('test_name') + raise e.InvalidReportHeader('test_name')
if not re.match('([0-9]+.)+[0-9]+$', report_header['test_version']): - raise InvalidReportHeader('test_version') + raise e.InvalidReportHeader('test_version')
return report_header
+class ReportHandler(OONIBHandler): + def initialize(self): + self.archive_dir = config.main.archive_dir + self.report_dir = config.main.report_dir + self.reports = config.reports + self.policy_file = config.main.policy_file + self.helpers = config.helpers + self.stale_time = config.main.stale_time + class UpdateReportMixin(object): def updateReport(self, report_id, parsed_request):
log.debug("Got this request %s" % parsed_request) - report_filename = os.path.join(config.main.report_dir, + report_filename = os.path.join(self.report_dir, report_id) - - config.reports[report_id].refresh() + + self.reports[report_id].refresh()
try: with open(report_filename, 'a+') as fd: - fdesc.setNonBlocking(fd.fileno()) - fdesc.writeToFD(fd.fileno(), parsed_request['content']) - except IOError as exc: + fd.write(parsed_request['content']) + except IOError: e.OONIBError(404, "Report not found") - self.write({}) + self.write({'status': 'success'})
-class NewReportHandlerFile(OONIBHandler, UpdateReportMixin): +class NewReportHandlerFile(ReportHandler, UpdateReportMixin): """ Responsible for creating and updating reports by writing to flat file. """ + inputHashes = None
def checkPolicy(self): policy = Policy() @@ -236,42 +247,31 @@ class NewReportHandlerFile(OONIBHandler, UpdateReportMixin): {'backend_version': 'XXX', 'report_id': 'XXX'}
""" - # XXX here we should validate and sanitize the request - try: - report_data = parseNewReportRequest(self.request.body) - except InvalidRequestField as exc: - raise e.InvalidRequestField(exc) - except MissingField as exc: - raise e.MissingRequestField(exc) + # Note: the request is being validated inside of parseNewReportRequest. + report_data = parseNewReportRequest(self.request.body)
log.debug("Parsed this data %s" % report_data)
software_name = str(report_data['software_name']) software_version = str(report_data['software_version']) - + probe_asn = str(report_data['probe_asn']) probe_cc = str(report_data.get('probe_cc', 'ZZ'))
self.testName = str(report_data['test_name']) self.testVersion = str(report_data['test_version']) - - if config.main.policy_file: + + if self.policy_file: try: self.inputHashes = report_data['input_hashes'] except KeyError: raise e.InputHashNotProvided self.checkPolicy() - + if 'content' in report_data: content = yaml.safe_load(report_data['content']) - try: - report_header = validate_report_header(content) - - except MissingReportHeaderKey, key: - raise e.MissingReportHeaderKey(key) + report_header = validate_report_header(content)
- except InvalidReportHeader, key: - raise e.InvalidReportHeader(key) else: content = { 'software_name': software_name, @@ -298,22 +298,26 @@ class NewReportHandlerFile(OONIBHandler, UpdateReportMixin):
# The report filename contains the timestamp of the report plus a # random nonce - report_filename = os.path.join(config.main.report_dir, report_id) + report_filename = os.path.join(self.report_dir, report_id)
response = { 'backend_version': config.backend_version, 'report_id': report_id } - + requested_helper = report_data.get('test_helper')
if requested_helper: try: - response['test_helper_address'] = config.helpers[requested_helper].address + response['test_helper_address'] = self.helpers[requested_helper].address except KeyError: raise e.TestHelperNotFound - - config.reports[report_id] = Report(report_id) + + self.reports[report_id] = Report(report_id, + self.stale_time, + self.report_dir, + self.archive_dir, + self.reports)
self.writeToReport(report_filename, content)
@@ -338,7 +342,7 @@ class NewReportHandlerFile(OONIBHandler, UpdateReportMixin):
self.updateReport(report_id, parsed_request)
-class UpdateReportHandlerFile(OONIBHandler, UpdateReportMixin): +class UpdateReportHandlerFile(ReportHandler, UpdateReportMixin): def post(self, report_id): try: parsed_request = json.loads(self.request.body) @@ -346,20 +350,17 @@ class UpdateReportHandlerFile(OONIBHandler, UpdateReportMixin): raise e.InvalidRequest self.updateReport(report_id, parsed_request)
-class ReportNotFound(Exception): - pass - -class CloseReportHandlerFile(OONIBHandler): +class CloseReportHandlerFile(ReportHandler): def get(self): pass
def post(self, report_id): - if report_id in config.reports: - config.reports[report_id].close() + if report_id in self.reports: + self.reports[report_id].close() else: raise e.ReportNotFound
-class PCAPReportHandler(OONIBHandler): +class PCAPReportHandler(ReportHandler): def get(self): pass
diff --git a/oonib/runner.py b/oonib/runner.py index c8fafa1..d413221 100644 --- a/oonib/runner.py +++ b/oonib/runner.py @@ -1,7 +1,3 @@ -# -*- encoding: utf-8 -*- -# -# :authors: Arturo Filastò, Isis Lovecruft -# :licence: see LICENSE for details """ In here we define a runner for the oonib backend system. """ @@ -13,14 +9,12 @@ import os
from shutil import rmtree
-from twisted.internet import reactor -from twisted.application import service, internet, app +from twisted.internet import reactor, endpoints from twisted.python.runtime import platformType
from txtorcon import TCPHiddenServiceEndpoint, TorConfig from txtorcon import launch_tor
-from oonib.report.api import reportAPI from oonib.api import ooniBackend, ooniBouncer from oonib.config import config
@@ -28,15 +22,16 @@ from oonib import oonibackend from oonib import log
from txtorcon import __version__ as txtorcon_version -if tuple(map(int, txtorcon_version.split('.'))) < (0,9,0): +if tuple(map(int, txtorcon_version.split('.'))) < (0, 9, 0): """ Fix for bug in txtorcon versions < 0.9.0 where TCPHiddenServiceEndpoint listens on all interfaces by default. """ def create_listener(self, proto): self._update_onion(self.hiddenservice.dir) - self.tcp_endpoint = TCP4ServerEndpoint(self.reactor, self.listen_port, # XXX missing import -- has this code ever been tested? - interface='127.0.0.1') + self.tcp_endpoint = endpoints.TCP4ServerEndpoint(self.reactor, + self.listen_port, + interface='127.0.0.1') d = self.tcp_endpoint.listen(self.protocolfactory) d.addCallback(self._add_attributes).addErrback(self._retry_local_port) return d @@ -64,13 +59,17 @@ else:
def setupHSEndpoint(self, tor_process_protocol, torconfig, endpoint): endpointName = endpoint.settings['name'] + def setup_complete(port): - print("Exposed %s Tor hidden service on httpo://%s" % (endpointName, - port.onion_uri)) + print("Exposed %s Tor hidden service " + "on httpo://%s" % (endpointName, port.onion_uri))
public_port = 80 - hs_endpoint = TCPHiddenServiceEndpoint(reactor, torconfig, public_port, - data_dir=os.path.join(torconfig.DataDirectory, endpointName)) + data_dir = os.path.join(torconfig.DataDirectory, endpointName) + hs_endpoint = TCPHiddenServiceEndpoint(reactor, + torconfig, + public_port, + data_dir=data_dir) d = hs_endpoint.listen(endpoint) d.addCallback(setup_complete) d.addErrback(self.txSetupFailed) diff --git a/oonib/testhelpers/dns_helpers.py b/oonib/testhelpers/dns_helpers.py index 9b2e5e3..fbf932b 100644 --- a/oonib/testhelpers/dns_helpers.py +++ b/oonib/testhelpers/dns_helpers.py @@ -1,14 +1,12 @@ -from twisted.internet.protocol import Factory, Protocol -from twisted.internet import reactor -from twisted.names import dns from twisted.names import client, server
from oonib.config import config
+ class DNSTestHelper(server.DNSServerFactory): - def __init__(self, authorities = None, - caches = None, clients = None, - verbose = 0): + def __init__(self, authorities=None, + caches=None, clients=None, + verbose=0): try: host, port = config.helpers.dns.split(':') port = int(port) @@ -17,8 +15,9 @@ class DNSTestHelper(server.DNSServerFactory): except: host, port = '8.8.8.8', 53 resolver = client.Resolver(servers=[(host, port)]) - server.DNSServerFactory.__init__(self, authorities = authorities, - caches = caches, clients = [resolver], - verbose = verbose) + server.DNSServerFactory.__init__(self, authorities=authorities, + caches=caches, clients=[resolver], + verbose=verbose) + def handleQuery(self, message, protocol, address): server.DNSServerFactory.handleQuery(self, message, protocol, address) diff --git a/oonib/testhelpers/http_helpers.py b/oonib/testhelpers/http_helpers.py index 245e08a..b2afc59 100644 --- a/oonib/testhelpers/http_helpers.py +++ b/oonib/testhelpers/http_helpers.py @@ -93,10 +93,11 @@ class SimpleHTTPChannel(basic.LineReceiver, policies.TimeoutMixin): headers_dict[k] = [] headers_dict[k].append(v)
- response = {'request_headers': self.headers, - 'request_line': self.requestLine, - 'headers_dict': headers_dict - } + response = { + 'request_headers': self.headers, + 'request_line': self.requestLine, + 'headers_dict': headers_dict + } json_response = json.dumps(response) self.transport.write('HTTP/1.1 200 OK\r\n\r\n') self.transport.write('%s' % json_response) diff --git a/oonib/testhelpers/ssl_helpers.py b/oonib/testhelpers/ssl_helpers.py index d511ddd..4b84a8c 100644 --- a/oonib/testhelpers/ssl_helpers.py +++ b/oonib/testhelpers/ssl_helpers.py @@ -3,7 +3,7 @@ from oonib.config import config
class SSLContext(ssl.DefaultOpenSSLContextFactory): def __init__(self, *args, **kw): - ssl.DefaultOpenSSLContextFactory.__init__(self, + ssl.DefaultOpenSSLContextFactory.__init__(self, config.helpers.ssl.private_key, config.helpers.ssl.certificate)
diff --git a/oonib/testhelpers/tcp_helpers.py b/oonib/testhelpers/tcp_helpers.py index 91c334b..614cf87 100644 --- a/oonib/testhelpers/tcp_helpers.py +++ b/oonib/testhelpers/tcp_helpers.py @@ -1,16 +1,16 @@ - from twisted.internet.protocol import Protocol, Factory, ServerFactory -from twisted.internet.error import ConnectionDone
from oonib.config import config from oonib import log from oonib.daphn3 import Daphn3Protocol from oonib.daphn3 import read_pcap, read_yaml
+ class TCPEchoProtocol(Protocol): def dataReceived(self, data): self.transport.write(data)
+ class TCPEchoHelper(Factory): """ A very simple echo protocol implementation @@ -24,8 +24,11 @@ elif config.helpers.daphn3.pcap_file: daphn3Steps = read_yaml(config.helpers.daphn3.pcap_file)
else: - daphn3Steps = [{'client': 'client_packet'}, - {'server': 'server_packet'}] + daphn3Steps = [ + {'client': 'client_packet'}, + {'server': 'server_packet'} + ] +
class Daphn3ServerProtocol(Daphn3Protocol): def nextStep(self):
tor-commits@lists.torproject.org