コード例 #1
0
    def test_good_cases(self):
        ''' Make sure it correctly counts the number of valid settings '''

        for prefix in ('privacy.', 'privacy_'):
            for trueval in (1, '1', 'true', 'on', 'yes'):

                self.assertEqual(
                    1,
                    privacy.count_valid({'%sinformed' % prefix: trueval},
                                        prefix))

                self.assertEqual(
                    1,
                    privacy.count_valid({'%scan_collect' % prefix: trueval},
                                        prefix))

                self.assertEqual(
                    1,
                    privacy.count_valid({'%scan_publish' % prefix: trueval},
                                        prefix))

                self.assertEqual(
                    3,
                    privacy.count_valid(
                        {
                            '%sinformed' % prefix: trueval,
                            '%scan_collect' % prefix: trueval,
                            '%scan_publish' % prefix: trueval
                        }, prefix))
コード例 #2
0
    def test_empty_cases(self):
        ''' Make sure it returns 0 when there is nothing interesting '''

        # Nothing in input
        self.assertEqual(0, privacy.count_valid({}, ""))

        # Wrong prefix
        self.assertEqual(
            0, privacy.count_valid({'privacy.informed': 1}, "privacy_"))
コード例 #3
0
ファイル: privacy.py プロジェクト: DavideAllavena/neubot
    def test_empty_cases(self):
        ''' Make sure it returns 0 when there is nothing interesting '''

        # Nothing in input
        self.assertEqual(0, privacy.count_valid(
          {}, ""))

        # Wrong prefix
        self.assertEqual(0, privacy.count_valid(
          {'privacy.informed': 1}, "privacy_"))
コード例 #4
0
ファイル: privacy.py プロジェクト: DavideAllavena/neubot
    def test_bad(self):
        ''' Make sure it returns -1 when settings are bad '''

        # False value
        self.assertEqual(-1, privacy.count_valid(
          {'privacy.informed': 0}, "privacy."))
        self.assertEqual(-1, privacy.count_valid(
          {'privacy.can_collect': 0}, "privacy."))
        self.assertEqual(-1, privacy.count_valid(
          {'privacy.can_publish': 0}, "privacy."))

        # Not all are True
        self.assertEqual(-1, privacy.count_valid(
          {'privacy.informed': 0,
           'privacy.can_collect': 0,
           'privacy.can_publish': 0},
          "privacy."))
        self.assertEqual(-1, privacy.count_valid(
          {'privacy.informed': 0,
           'privacy.can_collect': 0,
           'privacy.can_publish': 1},
          "privacy."))
        self.assertEqual(-1, privacy.count_valid(
          {'privacy.informed': 0,
           'privacy.can_collect': 1,
           'privacy.can_publish': 0},
          "privacy."))
        self.assertEqual(-1, privacy.count_valid(
          {'privacy.informed': 0,
           'privacy.can_collect': 1,
           'privacy.can_publish': 1},
          "privacy."))
        self.assertEqual(-1, privacy.count_valid(
          {'privacy.informed': 1,
           'privacy.can_collect': 0,
           'privacy.can_publish': 0},
          "privacy."))
        self.assertEqual(-1, privacy.count_valid(
          {'privacy.informed': 1,
           'privacy.can_collect': 0,
           'privacy.can_publish': 1},
          "privacy."))
        self.assertEqual(-1, privacy.count_valid(
          {'privacy.informed': 1,
           'privacy.can_collect': 1,
           'privacy.can_publish': 0},
          "privacy."))
コード例 #5
0
ファイル: runner_core.py プロジェクト: EverlastingFire/neubot
    def _do_run_queue(self, first_elem):
        ''' Actually run first element in queue '''

        # Make a copy of current settings
        conf = CONFIG.copy()

        # Make sure we abide to M-Lab policy
        if privacy.count_valid(conf, 'privacy.') != 3:
            privacy.complain()
            raise RuntimeError('runner_core: bad privacy settings')

        elif first_elem[0] == 'rendezvous':
            runner_rendezvous.run(conf['agent.master'], '9773')

        elif first_elem[0] == 'speedtest':
            uri = RUNNER_TESTS.test_to_negotiate_uri('speedtest')
            conf['speedtest.client.uri'] =  uri
            client = ClientSpeedtest(POLLER)
            client.configure(conf)
            client.connect_uri()

        elif first_elem[0] == 'bittorrent':
            uri = RUNNER_TESTS.test_to_negotiate_uri('bittorrent')
            conf['bittorrent._uri'] =  uri
            bittorrent.run(POLLER, conf)

        elif first_elem[0] == 'dload':
            RunnerDload(first_elem[2])

        elif first_elem[0] == 'raw':
            address = RUNNER_HOSTS.get_random_host()
            handler = RawNegotiate()
            handler.connect((address, 8080), CONFIG['prefer_ipv6'], 0, {})

        elif first_elem[0] == 'mlab-ns':
            handler = RunnerMlabns()
            if not first_elem[2]:
                extra = {'policy': ''}  # get closest server by default
            else:
                extra = first_elem[2]
            handler.connect(('mlab-ns.appspot.com', 80),
              CONFIG['prefer_ipv6'], 0, extra)

        elif first_elem[0] in self.dynamic_tests:
            address = RUNNER_HOSTS.get_random_host()
            port = 80  # XXX
            self.dynamic_tests[first_elem[0]]["test_func"]({
                "address": address,
                "conf": CONFIG.copy(),
                "poller": POLLER,
                "port": port,
            })

        else:
            raise RuntimeError('runner_core: asked to run an unknown test')
コード例 #6
0
ファイル: privacy.py プロジェクト: DavideAllavena/neubot
    def test_good_cases(self):
        ''' Make sure it correctly counts the number of valid settings '''

        for prefix in ('privacy.', 'privacy_'):
            for trueval in (1, '1', 'true', 'on', 'yes'):

                self.assertEqual(1, privacy.count_valid(
                  {'%sinformed' % prefix: trueval},
                  prefix))

                self.assertEqual(1, privacy.count_valid(
                  {'%scan_collect' % prefix: trueval},
                  prefix))

                self.assertEqual(1, privacy.count_valid(
                  {'%scan_publish' % prefix: trueval},
                  prefix))

                self.assertEqual(3, privacy.count_valid(
                  {'%sinformed' % prefix: trueval,
                   '%scan_collect' % prefix: trueval,
                   '%scan_publish' % prefix: trueval},
                  prefix))
コード例 #7
0
ファイル: runner_core.py プロジェクト: felipebusnello/neubot
    def _do_run_queue(self):
        ''' Actually run first element in queue '''

        # Make a copy of current settings
        conf = CONFIG.copy()

        # Make sure we abide to M-Lab policy
        if privacy.count_valid(conf, 'privacy.') != 3:
            privacy.complain()
            raise RuntimeError('Bad privacy settings')

        # Run rendezvous
        elif self.queue[0][0] == 'rendezvous':
            uri = "http://%s:9773/rendezvous" % conf['agent.master']
            runner_rendezvous.run(uri)

        # Run speedtest
        elif self.queue[0][0] == 'speedtest':
            uri = RUNNER_TESTS.test_to_negotiate_uri('speedtest')
            #
            # If we have no negotiate URI for this test, possibly
            # because we are offline, abort it.
            #
            if not uri:
                raise RuntimeError('No negotiate URI for speedtest')
            conf['speedtest.client.uri'] =  uri
            client = ClientSpeedtest(POLLER)
            client.configure(conf)
            client.connect_uri()

        # Run bittorrent
        elif self.queue[0][0] == 'bittorrent':
            uri = RUNNER_TESTS.test_to_negotiate_uri('bittorrent')
            #
            # If we have no negotiate URI for this test, possibly
            # because we are offline, abort it.
            #
            if not uri:
                raise RuntimeError('No negotiate URI for bittorrent')
            conf['bittorrent._uri'] =  uri
            bittorrent.run(POLLER, conf)

        # Run dload
        elif self.queue[0][0] == 'dload':
            RunnerDload(self.queue[0][2])

        # Safety net
        else:
            raise RuntimeError('Asked to run an unknown test')
コード例 #8
0
ファイル: macos.py プロジェクト: DavideAllavena/neubot
def __should_adjust_privacy(database_path):

    ''' Connect to the daemon, get privacy settings and return
        true if the user should adjust privacy settings '''

    #
    # Portions of this function can be shared between this
    # notifier and the UNIX one.  At the moment there's a
    # small amount of code duplication.
    #

    try:

        address, port = '127.0.0.1', '9774'

        connection = sqlite3.connect(database_path)
        cursor = connection.cursor()
        cursor.execute('SELECT * FROM config;')
        for name, value in cursor:
            if name == 'agent.api.address':
                address = value
            elif name == 'agent.api.port':
                port = value
        connection.close()

        connection = httplib.HTTPConnection(address, port)
        connection.request('GET', '/api/config')

        response = connection.getresponse()
        if response.status != 200:
            raise RuntimeError('Invalid response code: %d' % response.status)

        body = response.read()
        connection.close()

        dictionary = json.loads(body)
        if privacy.count_valid(dictionary, 'privacy.') != 3:
            # Should adjust settings
            return "http://%s:%s/" % (address, port)

    except SystemExit:
        raise
    except:
        syslog.syslog(syslog.LOG_ERR, '%s' %
          str(asyncore.compact_traceback()))

    # No need to adjust settings
    return None
コード例 #9
0
ファイル: runner_core.py プロジェクト: DavideAllavena/neubot
    def run_queue(self):
        ''' If possible run the first test in queue '''

        # Adapted from neubot/rendezvous/client.py

        if not self.queue:
            return
        if self.running:
            return

        #
        # Subscribe BEFORE starting the test, otherwise we
        # may miss the 'testdone' event if the connection
        # to the negotiator service fails, and we will stay
        # stuck forever.
        #
        NOTIFIER.subscribe('testdone', self.test_done)

        # Prevent concurrent tests
        self.running = True

        # Make a copy of current settings
        conf = CONFIG.copy()

        # Make sure we abide to M-Lab policy
        if privacy.count_valid(conf, 'privacy.') != 3:
            privacy.complain()
            NOTIFIER.publish('testdone')

        # Run speedtest
        elif self.queue[0][0] == 'speedtest':
            conf['speedtest.client.uri'] =  self.queue[0][1]
            client = ClientSpeedtest(POLLER)
            client.configure(conf)
            client.connect_uri()

        # Run bittorrent
        elif self.queue[0][0] == 'bittorrent':
            conf['bittorrent._uri'] =  self.queue[0][1]
            bittorrent.run(POLLER, conf)

        # Safety net
        else:
            LOG.error('Asked to run an unknown test')
            NOTIFIER.publish('testdone')
コード例 #10
0
ファイル: unix.py プロジェクト: felipebusnello/neubot
def __should_adjust_privacy(database_path):

    ''' Connect to the daemon, get privacy settings and return
        true if the user should adjust privacy settings '''

    try:

        address, port = '127.0.0.1', '9774'

        connection = sqlite3.connect(database_path)
        cursor = connection.cursor()
        cursor.execute('SELECT * FROM config;')
        for name, value in cursor:
            if name == 'agent.api.address':
                address = value
            elif name == 'agent.api.port':
                port = value
        connection.close()

        connection = lib_http.HTTPConnection(address, port)
        connection.request('GET', '/api/config')

        response = connection.getresponse()
        if response.status != 200:
            raise RuntimeError('Invalid response code: %d' % response.status)

        body = response.read()
        connection.close()

        dictionary = json.loads(body)
        if privacy.count_valid(dictionary, 'privacy.') != 3:
            # Should adjust settings
            return True

    except SystemExit:
        raise
    except:
        syslog.syslog(syslog.LOG_ERR, '%s' %
          str(asyncore.compact_traceback()))

    # No need to adjust settings
    return False
コード例 #11
0
ファイル: server.py プロジェクト: DavideAllavena/neubot
    def process_request(self, stream, request):
        m = marshal.unmarshal_object(request.body.read(),
          "application/xml", compat.RendezvousRequest)

        m1 = compat.RendezvousResponse()

        #
        # If we don't say anything the rendezvous server is not
        # going to prompt for updates.  We need to specify the
        # updated version number explicitly when we start it up.
        # This should guarantee that we do not advertise -rc
        # releases and other weird things.
        #
        version = self.conf["rendezvous.server.update_version"]
        if version and m.version:
            diff = LibVersion.compare(version, m.version)
            LOG.debug('rendezvous: version=%s m.version=%s diff=%f' % (
                      version, m.version, diff))
            if diff > 0:
                m1.update["uri"] = self.conf["rendezvous.server.update_uri"]
                m1.update["version"] = version

        #
        # Select test server address.
        # The default test server is the master server itself.
        # If we know the country, lookup the list of servers for
        # that country in the database.
        # We only redirect to other servers clients that have
        # agreed to give us the permission to publish, in order
        # to be compliant with M-Lab policy.
        # If there are no servers for that country, register
        # the master server for the country so that we can notice
        # we have new users and can take the proper steps to
        # deploy nearby servers.
        #
        server = self.conf.get("rendezvous.server.default",
                               "master.neubot.org")
        LOG.debug("* default test server: %s" % server)

        #
        # Backward compatibility: the variable name changed from
        # can_share to can_publish after Neubot 0.4.5
        #
        request_body = m.__dict__.copy()
        if 'privacy_can_share' in request_body:
            request_body['privacy_can_publish'] = request_body[
              'privacy_can_share']
            del request_body['privacy_can_share']

        # Redirect IFF have ALL privacy permissions
        if privacy.count_valid(request_body, 'privacy_') == 3:
            agent_address = stream.peername[0]
            country = GEOLOCATOR.lookup_country(agent_address)
            if country:
                servers = table_geoloc.lookup_servers(DATABASE.connection(),
                                                      country)
                if not servers:
                    LOG.info("* learning new country: %s" % country)
                    table_geoloc.insert_server(DATABASE.connection(),
                                               country, server)
                    servers = [server]
                server = random.choice(servers)
                LOG.debug("* selected test server: %s" % server)

        if "speedtest" in m.accept:
            m1.available["speedtest"] = [ "http://%s/speedtest" % server ]

        if "bittorrent" in m.accept:
            m1.available["bittorrent"] = [ "http://%s/" % server ]

        #
        # Neubot <=0.3.7 expects to receive an XML document while
        # newer Neubots want a JSON.  I hope old clients will upgrade
        # pretty soon.
        #
        if m.version and LibVersion.compare(m.version, "0.3.7") >= 0:
            s = marshal.marshal_object(m1, "application/json")
            mimetype = "application/json"
        else:
            s = compat.adhoc_marshaller(m1)
            mimetype = "text/xml"

        stringio = StringIO.StringIO()
        stringio.write(s)
        stringio.seek(0)

        response = Message()
        response.compose(code="200", reason="Ok",
          mimetype=mimetype, body=stringio)
        stream.send_response(request, response)
コード例 #12
0
ファイル: config_api.py プロジェクト: EverlastingFire/neubot
def config_api(stream, request, query):

    ''' Implements /api/config API '''

    # Adapted from neubot/api/server.py

    #
    # Fetch and process common options from the query
    # string, for now the only implemented option is
    # debug, which modifies the semantic to return text
    # for humans instead of JSON.
    #

    mimetype = 'application/json'
    indent = None

    options = cgi.parse_qs(query)

    if utils.intify(options.get('debug', ['0'])[0]):
        mimetype = 'text/plain'
        indent = 4

    #
    # Now that we know the response format, decide what is
    # the content of the response.  If the labels option is
    # available we return the documentation coupled with a
    # setting.  When the method is not POST, return instead
    # the name and value of each setting.
    #

    if utils.intify(options.get('labels', ['0'])[0]):
        obj = CONFIG.descriptions
    elif request.method != 'POST':
        obj = CONFIG.conf
    else:

        #
        # When the method is POST we need to read the
        # new settings from the request body.  Settings
        # are a x-www-form-urlencoded dictionary to
        # ease AJAX programming.
        #

        body = request.body.read()
        updates = marshal.qs_to_dictionary(body)

        #
        # PRE-update checks.  We need to make sure that
        # the following things are True:
        #
        # 1. that the incoming dictionary does not contain
        #    invalid privacy settings;
        #
        # 2. that the interval between automatic tests is
        #    either reasonable or set to zero, which means
        #    that it needs to be extracted randomly.
        #

        count = privacy.count_valid(updates, 'privacy.')
        if count < 0:
            raise ConfigError('Passed invalid privacy settings')

        agent_interval = int(updates.get('agent.interval', 0))
        if agent_interval != 0 and agent_interval < 1380:
            raise ConfigError('Passed invalid agent.interval')

        # Merge settings
        CONFIG.merge_api(updates, DATABASE.connection())

        #
        # Update the state, such that, if the AJAX code is
        # tracking the state it gets a notification that
        # some configurations variable have been modified.
        # Given that we communicate the update via that
        # channel, the response body is an empty dict to
        # keep happy the AJAX code.
        #

        STATE.update('config', updates)
        obj = '{}'

    #
    # Now that we know the body, prepare and send
    # the response for the client.
    #

    response = Message()

    body = json.dumps(obj, sort_keys=True, indent=indent)
    response.compose(code="200", reason="Ok", body=body, mimetype=mimetype)
    stream.send_response(request, response)
コード例 #13
0
ファイル: server.py プロジェクト: claudiuperta/neubot
    def process_request(self, stream, request):
        """ Process rendezvous request """

        if request["content-type"] == "application/json":
            ibody = marshal.unmarshal_object(request.body.read(), "application/json", compat.RendezvousRequest)
        else:
            ibody = marshal.unmarshal_object(request.body.read(), "application/xml", compat.RendezvousRequest)

        obody = compat.RendezvousResponse()

        #
        # If we don't say anything the rendezvous server is not
        # going to prompt for updates.  We need to specify the
        # updated version number explicitly when we start it up.
        # This should guarantee that we do not advertise -rc
        # releases and other weird things.
        #
        version = self.conf["rendezvous.server.update_version"]
        if version and ibody.version:
            diff = utils_version.compare(version, ibody.version)
            logging.debug("rendezvous: version=%s ibody.version=%s diff=%f", version, ibody.version, diff)
            if diff > 0:
                obody.update["uri"] = "http://neubot.org/"
                obody.update["version"] = version

        #
        # Select test server address.
        # The default test server is the master server itself.
        # If we know the country, lookup the list of servers for
        # that country in the database.
        # We only redirect to other servers clients that have
        # agreed to give us the permission to publish, in order
        # to be compliant with M-Lab policy.
        # If there are no servers for that country, register
        # the master server for the country so that we can notice
        # we have new users and can take the proper steps to
        # deploy nearby servers.
        #
        server = self.conf.get("rendezvous.server.default", "master.neubot.org")
        logging.debug("* default test server: %s", server)

        #
        # Backward compatibility: the variable name changed from
        # can_share to can_publish after Neubot 0.4.5
        #
        request_body = ibody.__dict__.copy()
        if "privacy_can_share" in request_body:
            request_body["privacy_can_publish"] = request_body["privacy_can_share"]
            del request_body["privacy_can_share"]

        # Redirect IFF have ALL privacy permissions
        if privacy.count_valid(request_body, "privacy_") == 3:
            agent_address = stream.peername[0]
            country = GEOLOCATOR.lookup_country(agent_address)
            if country:
                servers = table_geoloc.lookup_servers(DATABASE.connection(), country)
                if not servers:
                    logging.info("* learning new country: %s", country)
                    table_geoloc.insert_server(DATABASE.connection(), country, server)
                    servers = [server]
                server = random.choice(servers)
                logging.info("rendezvous_server: %s[%s] -> %s", agent_address, country, server)

        else:
            logging.warning("rendezvous_server: cannot redirect to M-Lab: %s", request_body)

        #
        # We require at least informed and can_collect since 0.4.4
        # (released 25 October 2011), so stop clients with empty
        # privacy settings, who were still using master.
        #
        if privacy.collect_allowed(request_body):
            #
            # Note: Here we will have problems if we store unquoted
            # IPv6 addresses into the database.  Because the resulting
            # URI won't be valid.
            #
            if "speedtest" in ibody.accept:
                obody.available["speedtest"] = ["http://%s/speedtest" % server]
            if "bittorrent" in ibody.accept:
                obody.available["bittorrent"] = ["http://%s/" % server]

        #
        # Neubot <=0.3.7 expects to receive an XML document while
        # newer Neubots want a JSON.  I hope old clients will upgrade
        # pretty soon.
        #
        if ibody.version and utils_version.compare(ibody.version, "0.3.7") >= 0:
            body = marshal.marshal_object(obody, "application/json")
            mimetype = "application/json"
        else:
            body = compat.adhoc_marshaller(obody)
            mimetype = "text/xml"

        response = Message()
        response.compose(code="200", reason="Ok", mimetype=mimetype, body=body)
        stream.send_response(request, response)
コード例 #14
0
    def test_bad(self):
        ''' Make sure it returns -1 when settings are bad '''

        # False value
        self.assertEqual(
            -1, privacy.count_valid({'privacy.informed': 0}, "privacy."))
        self.assertEqual(
            -1, privacy.count_valid({'privacy.can_collect': 0}, "privacy."))
        self.assertEqual(
            -1, privacy.count_valid({'privacy.can_publish': 0}, "privacy."))

        # Not all are True
        self.assertEqual(
            -1,
            privacy.count_valid(
                {
                    'privacy.informed': 0,
                    'privacy.can_collect': 0,
                    'privacy.can_publish': 0
                }, "privacy."))
        self.assertEqual(
            -1,
            privacy.count_valid(
                {
                    'privacy.informed': 0,
                    'privacy.can_collect': 0,
                    'privacy.can_publish': 1
                }, "privacy."))
        self.assertEqual(
            -1,
            privacy.count_valid(
                {
                    'privacy.informed': 0,
                    'privacy.can_collect': 1,
                    'privacy.can_publish': 0
                }, "privacy."))
        self.assertEqual(
            -1,
            privacy.count_valid(
                {
                    'privacy.informed': 0,
                    'privacy.can_collect': 1,
                    'privacy.can_publish': 1
                }, "privacy."))
        self.assertEqual(
            -1,
            privacy.count_valid(
                {
                    'privacy.informed': 1,
                    'privacy.can_collect': 0,
                    'privacy.can_publish': 0
                }, "privacy."))
        self.assertEqual(
            -1,
            privacy.count_valid(
                {
                    'privacy.informed': 1,
                    'privacy.can_collect': 0,
                    'privacy.can_publish': 1
                }, "privacy."))
        self.assertEqual(
            -1,
            privacy.count_valid(
                {
                    'privacy.informed': 1,
                    'privacy.can_collect': 1,
                    'privacy.can_publish': 0
                }, "privacy."))