Ejemplo n.º 1
0
    def collect(self, stream, request_body):
        """ Invoked when we must save the result of a session """

        sha256 = self._stream_to_sha256(stream)

        if sha256 not in self.peers:
            raise RuntimeError("dash: not authorized: %s", sha256)

        # Note: no more than one collect per session
        result = self.peers.pop(sha256)

        logging.debug("dash: del sha256 (OK): %s", sha256)

        server_timestamp = utils.timestamp()

        BACKEND.store_generic("dash", {
                                       "srvr_schema_version": 3,
                                       "srvr_timestamp": server_timestamp,
                                       "client": request_body,
                                       "server": result,
                                      })

        #
        # Return back, at a minimum, the server timestamp.
        # TODO Also gather and return Web100 stats.
        #
        for index in range(len(request_body)):
            if index <= len(result):
                result.append({})
            result[index]["timestamp"] = server_timestamp

        return result
Ejemplo n.º 2
0
def main(args):
    """ Main function """
    try:
        options, arguments = getopt.getopt(args[1:], "6A:np:vy")
    except getopt.error:
        sys.exit("usage: neubot skype [-6nvy] [-A address] [-p port]")
    if arguments:
        sys.exit("usage: neubot skype [-6nvy] [-A address] [-p port]")

    prefer_ipv6 = 0
    # address = 'master.neubot.org'
    address = "localhost"
    runner = 1
    port = 8080
    noisy = 0
    fakeprivacy = 0
    for name, value in options:
        if name == "-6":
            prefer_ipv6 = 1
        elif name == "-A":
            address = value
        elif name == "-n":
            runner = 0
        elif name == "-p":
            port = int(value)
        elif name == "-v":
            noisy = 1
        elif name == "-y":
            fakeprivacy = 1

    if os.path.isfile(DATABASE.path):
        DATABASE.connect()
        CONFIG.merge_database(DATABASE.connection())
    else:
        logging.warning("skype: database file is missing: %s", DATABASE.path)
        BACKEND.use_backend("null")
    if noisy:
        log.set_verbose()
    if runner:
        result = runner_clnt.runner_client(
            CONFIG["agent.api.address"], CONFIG["agent.api.port"], CONFIG["verbose"], "skype"
        )
        if result:
            sys.exit(0)

    logging.info("skype: running the test in the local process context...")
    if not fakeprivacy and not privacy.allowed_to_run():
        privacy.complain()
        logging.info("skype: otherwise use -y option to temporarily provide " "privacy permissions")
        sys.exit(1)

    handler = SkypeNegotiate()
    handler.connect((address, port), prefer_ipv6, 0, {})
    POLLER.loop()
Ejemplo n.º 3
0
def main(args):
    """ Main function """

    if not system.has_enough_privs():
        sys.exit('FATAL: you must be root')

    common.main("agent", "Run in background, periodically run tests", args)

    conf = CONFIG.copy()

    privacy.complain_if_needed()

    BACKEND.use_backend("neubot")
    BACKEND.datadir_init()

    # FIXME We're ignoring agent.api.{address,port} that are now
    # deprecated and should be removed soon.
    background_api.start_api()

    if conf["agent.daemonize"]:
        LOG.redirect()
        system.go_background()

    if conf["agent.use_syslog"]:
        LOG.redirect()

    #
    # When we run as an agent we also save logs into
    # the database, to easily access and show them via
    # the web user interface.
    #
    LOG.use_database()

    logging.info('%s for POSIX: starting up', utils_version.PRODUCT)

    system.drop_privileges()

    if os.getuid() == 0 or os.geteuid() == 0:
        logging.error('agent: still running as root')
        os._exit(1)

    if conf["agent.rendezvous"]:
        BACKGROUND_RENDEZVOUS.start()

    POLLER.loop()

    logging.info('%s for POSIX: shutting down', utils_version.PRODUCT)
    LOG.writeback()

    #
    # Make sure that we do not leave the database
    # in an inconsistent state.
    #
    DATABASE.close()
Ejemplo n.º 4
0
 def collect(self, stream, request_body):
     ''' Invoked when we must save the result of a session '''
     sha512 = self._stream_to_sha512(stream)
     if sha512 not in self.peers:
         raise RuntimeError('negotiate_server_raw: not authorized')
     else:
         result = self.peers[sha512]
         # Note: no more than one collect per session
         del self.peers[sha512]
         logging.debug('negotiate_server_raw: del sha512 OK: %s',
           sha512.encode('hex'))
         complete_result = {'client': request_body, 'server': result}
         BACKEND.store_raw(complete_result)
         return result
Ejemplo n.º 5
0
def main(args):
    """ Main function """
    try:
        options, arguments = getopt.getopt(args[1:], "6A:fp:v")
    except getopt.error:
        sys.exit("usage: neubot speedtest [-6fv] [-A address] [-p port]")
    if arguments:
        sys.exit("usage: neubot speedtest [-6fv] [-A address] [-p port]")

    prefer_ipv6 = 0
    address = "master.neubot.org"
    force = 0
    port = 8080
    noisy = 0
    for name, value in options:
        if name == "-6":
            prefer_ipv6 = 1
        elif name == "-A":
            address = value
        elif name == "-f":
            force = 1
        elif name == "-p":
            port = int(value)
        elif name == "-v":
            noisy = 1

    if os.path.isfile(DATABASE.path):
        DATABASE.connect()
        CONFIG.merge_database(DATABASE.connection())
    else:
        logging.warning("speedtest: database file is missing: %s", DATABASE.path)
        BACKEND.use_backend("null")
    if noisy:
        log.set_verbose()

    conf = CONFIG.copy()
    conf["speedtest.client.uri"] = "http://%s:%d/" % (address, port)
    conf["prefer_ipv6"] = prefer_ipv6

    if not force:
        if runner_clnt.runner_client(conf["agent.api.address"], conf["agent.api.port"], CONFIG["verbose"], "speedtest"):
            sys.exit(0)
        logging.warning("speedtest: failed to contact Neubot; is Neubot running?")
        sys.exit(1)

    logging.info("speedtest: run the test in the local process context...")
    client = ClientSpeedtest(POLLER)
    client.configure(conf)
    client.connect_uri()
    POLLER.loop()
Ejemplo n.º 6
0
def main(args):
    ''' Main function '''
    try:
        options, arguments = getopt.getopt(args[1:], '6A:fp:v')
    except getopt.error:
        sys.exit('usage: neubot raw [-6fv] [-A address] [-p port]')
    if arguments:
        sys.exit('usage: neubot raw [-6fv] [-A address] [-p port]')

    prefer_ipv6 = 0
    address = 'master.neubot.org'
    force = 0
    port = 8080
    noisy = 0
    for name, value in options:
        if name == '-6':
            prefer_ipv6 = 1
        elif name == '-A':
            address = value
        elif name == '-f':
            force = 1
        elif name == '-p':
            port = int(value)
        elif name == '-v':
            noisy = 1

    if os.path.isfile(DATABASE.path):
        DATABASE.connect()
        CONFIG.merge_database(DATABASE.connection())
    else:
        logging.warning('raw: database file is missing: %s', DATABASE.path)
        BACKEND.use_backend('null')
    if noisy:
        log.set_verbose()

    if not force:
        result = runner_clnt.runner_client(CONFIG['agent.api.address'],
          CONFIG['agent.api.port'], CONFIG['verbose'], 'raw')
        if result:
            sys.exit(0)
        logging.warning('raw: failed to contact Neubot; is Neubot running?')
        sys.exit(1)

    logging.info('raw: run the test in the local process context...')
    handler = RawNegotiate()
    handler.connect((address, port), prefer_ipv6, 0, {})
    POLLER.loop()
Ejemplo n.º 7
0
def main(args):
    ''' Main() function '''

    try:
        options, arguments = getopt.getopt(args[1:], '')
    except getopt.error:
        sys.exit('usage: neubot background_win32')
    if options or arguments:
        sys.exit('usage: neubot background_win32')

    # Read settings from database
    CONFIG.merge_database(DATABASE.connection())

    BACKEND.use_backend("neubot")
    BACKEND.datadir_init()

    #
    # Save logs into the database, to easily access
    # and show them via the web user interface.
    #
    LOG.use_database()

    logging.info('%s for Windows: starting up', utils_version.PRODUCT)

    # Complain if privacy settings are not OK
    privacy.complain_if_needed()

    background_api.start_api()
    BACKGROUND_RENDEZVOUS.start()

    __start_updater()

    POLLER.loop()

    logging.info('%s for Windows: shutting down', utils_version.PRODUCT)
    LOG.writeback()

    #
    # Make sure that we do not leave the database
    # in an inconsistent state.
    #
    DATABASE.close()
Ejemplo n.º 8
0
    def collect(self, stream, request_body):
        ''' Invoked when we must save the result of a session '''
        sha1 = self._stream_to_sha1(stream)
        if sha1 not in self.peers:
            raise RuntimeError('Not authorized to collect')
        else:

            # Note: no more than one collect per session
            result = self.peers[sha1]
            del self.peers[sha1]

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

            #
            # Note that the following is not a bug: it's just that
            # the server saves results using the point of view of the
            # client, i.e. upload_speed _is_ client's upload speed.
            #
            request_body['timestamp'] = result['timestamp']
            request_body['upload_speed'] = result['upload_speed']

            if privacy.collect_allowed(request_body):
                BACKEND.bittorrent_store(request_body)
            else:
                logging.warning('* bad privacy settings: %s', str(stream))

            #
            # After we've saved the result into the dictionary we
            # can add extra information we would like to return to
            # the client.
            #
            request_body['target_bytes'] = result['target_bytes']
            return request_body
Ejemplo n.º 9
0
    def collect_legacy(self, stream, request_body, request):
        ''' Invoked when we must save the result of a session '''
        ident = str(hash(stream)).encode('hex')
        if ident not in self.clients:
            #
            # Before Neubot 0.4.2 we were using multiple connections
            # for speedtest, which were used both for testing and for
            # negotiating/collecting.  Sometimes the connection used
            # to collect is not the one used to negotiate: the code
            # uses the one that terminates the upload first.
            # When this happens we inspect the Authorization header
            # before deciding the collect request is an abuse.
            #
            authorization = request['Authorization']
            if authorization not in self.clients:
                raise RuntimeError('Not authorized to collect')
            else:
                logging.warning('skype: working around multiple conns '
                                'issue')
                ident = authorization

        # Note: no more than one collect per session
        self.clients.remove(ident)

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

        if privacy.collect_allowed(request_body):
            # TODO (claudiu) Implement BACKEND.skype_test_store()
            BACKEND.speedtest_store(request_body)
        else:
            logging.warning('* bad privacy settings: %s', str(stream))

        return {}
Ejemplo n.º 10
0
    def got_response(self, stream, request, response):

        if response.code != "200":
            logging.warning("dash: http request error: %s", response.code)
            stream.close()
            return

        if self.state == STATE_NEGOTIATE:

            response_body = json.load(response.body)

            #
            # Note: the following are the standard fields that
            # the negotiate API call MUST return.
            #
            self.authorization = response_body["authorization"]
            self.queue_pos = response_body["queue_pos"]
            self.real_address = response_body["real_address"]
            self.unchoked = response_body["unchoked"]

            if not self.unchoked:
                logging.info("dash: negotiate... done (queue pos %d)",
                             self.queue_pos)
                STATE.update("negotiate", {"queue_pos": self.queue_pos})
                self.connection_ready(stream)
                return

            logging.info("dash: negotiate... done (unchoked)")

            self.stream = stream

            #
            # The server may override the vector of rates with a "better"
            # vector of rates of its choice.
            #
            rates = list(response_body.get("dash_rates", DASH_RATES))

            self.client = DASHClientSmpl(self.poller, self, rates)
            self.client.configure(self.conf.copy())
            self.client.connect((self.stream.peername[0], 80))  # XXX

        elif self.state == STATE_COLLECT:

            response_body = json.load(response.body)

            #
            # We store each iteration of the test as a separate row of
            # the backend. We also add a whole test timestamp, to allow
            # one to understand which row belong to the same test.
            #
            whole_test_timestamp = utils.timestamp()

            for index, elem in enumerate(self.measurements):
                elem["clnt_schema_version"] = 3
                elem["whole_test_timestamp"] = whole_test_timestamp
                if index < len(response_body):
                    elem["srvr_data"] = response_body[index]
                BACKEND.store_generic("dash", elem)

            stream.close()

        else:
            raise RuntimeError("dash: internal error")
Ejemplo n.º 11
0
def api_data(stream, request, query):
    ''' Get data stored on the local database '''
    since, until = -1, -1
    test = ''

    dictionary = cgi.parse_qs(query)

    if "test" in dictionary:
        test = str(dictionary["test"][0])
    if "since" in dictionary:
        since = int(dictionary["since"][0])
    if "until" in dictionary:
        until = int(dictionary["until"][0])

    if test == 'bittorrent':
        table = table_bittorrent
    elif test == 'speedtest':
        table = table_speedtest
    elif test == 'raw':
        table = table_raw
    else:
        table = None

    indent, mimetype, sort_keys = None, "application/json", False
    if "debug" in dictionary and utils.intify(dictionary["debug"][0]):
        indent, mimetype, sort_keys = 4, "text/plain", True

    response = Message()

    if table:
        lst = table.listify(DATABASE.connection(), since, until)

    #
    # TODO We should migrate all the tests to use the new
    # generic interface. At that point, we can also change
    # the API to access "pages" of data by index.
    #
    # Until we change the API, we have an API that allows
    # the caller to specify date ranges. For this reason
    # below we emulate the date-ranges semantics provided
    # by database-based tests.
    #
    # Note: we assume that, whatever the test structure,
    # there is a field called "timestamp".
    #
    else:
        lst = []
        indexes = [None]
        indexes.extend(range(16))
        for index in indexes:
            tmp = BACKEND.walk_generic(test, index)
            if not tmp:
                break
            found_start = False
            for elem in reversed(tmp):
                if until >= 0 and elem["timestamp"] > until:
                    continue
                if since >= 0 and elem["timestamp"] < since:
                    found_start = True
                    break
                lst.append(elem)
            if found_start:
                break

    body = json.dumps(lst, indent=indent, sort_keys=sort_keys)
    response.compose(code="200", reason="Ok", body=body, mimetype=mimetype)
    stream.send_response(request, response)
Ejemplo n.º 12
0
def main(args):
    """ Main function """
    try:
        options, arguments = getopt.getopt(args[1:], '6A:fp:v')
    except getopt.error:
        sys.exit('usage: neubot speedtest [-6fv] [-A address] [-p port]')
    if arguments:
        sys.exit('usage: neubot speedtest [-6fv] [-A address] [-p port]')

    prefer_ipv6 = 0
    address = 'master.neubot.org'
    force = 0
    port = 8080
    noisy = 0
    for name, value in options:
        if name == '-6':
            prefer_ipv6 = 1
        elif name == '-A':
            address = value
        elif name == '-f':
            force = 1
        elif name == '-p':
            port = int(value)
        elif name == '-v':
            noisy = 1

    if os.path.isfile(DATABASE.path):
        DATABASE.connect()
        CONFIG.merge_database(DATABASE.connection())
    else:
        logging.warning('speedtest: database file is missing: %s',
                        DATABASE.path)
        BACKEND.use_backend('null')
    if noisy:
        log.set_verbose()

    conf = CONFIG.copy()
    conf["speedtest.client.uri"] = "http://%s:%d/" % (address, port)
    conf["prefer_ipv6"] = prefer_ipv6

    if not force:
        if runner_clnt.runner_client(conf["agent.api.address"],
                                     conf["agent.api.port"],
                                     CONFIG['verbose'],
                                     "speedtest"):
            sys.exit(0)
        logging.warning(
          'speedtest: failed to contact Neubot; is Neubot running?')
        sys.exit(1)

    logging.info('speedtest: run the test in the local process context...')
    client = ClientSpeedtest(POLLER)
    client.configure(conf)

    #
    # XXX Quick and dirty fix such that `neubot speedtest` when
    # there is no daemon running considers both the master and
    # the backup master server.  At the same time, respect user
    # choices if she overrides the default URI.
    #
    if CONFIG['speedtest.client.uri'] == 'http://master.neubot.org/':
        client.connect(('localhost', 8080))
    else:
        client.connect_uri()

    POLLER.loop()
Ejemplo n.º 13
0
 def _save_results(opaque):
     ''' Save test results '''
     local_result, remote_result = opaque
     remote_result['web100_snap'] = {}  # XXX disabled for 0.4.15
     complete_result = {'client': local_result, 'server': remote_result}
     BACKEND.store_skype(complete_result)
Ejemplo n.º 14
0
def main(args):
    """ Starts the server module """

    if not system.has_enough_privs():
        sys.exit("FATAL: you must be root")

    try:
        options, arguments = getopt.getopt(args[1:], "b:D:dv")
    except getopt.error:
        sys.exit(USAGE)
    if arguments:
        sys.exit(USAGE)

    backend = "mlab"
    for name, value in options:
        if name == "-b":
            backend = value
        elif name == "-D":
            name, value = value.split("=", 1)
            if name not in VALID_MACROS:
                sys.exit(USAGE)
            SETTINGS[name] = int(value)
        elif name == "-d":
            SETTINGS["server.daemonize"] = 0
        elif name == "-v":
            CONFIG["verbose"] = 1

    logging.debug("server: using backend: %s... in progress", backend)
    if backend == "mlab":
        FILESYS.datadir_init()
        BACKEND.use_backend("mlab")
    elif backend == "neubot":
        DATABASE.connect()
        BACKEND.use_backend("neubot")
    else:
        BACKEND.use_backend("null")
    logging.debug("server: using backend: %s... complete", backend)

    for name, value in SETTINGS.items():
        CONFIG[name] = value

    conf = CONFIG.copy()

    #
    # Configure our global HTTP server and make
    # sure that we don't provide filesystem access
    # even by mistake.
    #
    conf["http.server.rootdir"] = ""
    HTTP_SERVER.configure(conf)

    #
    # New-new style: don't bother with abstraction and start the f*****g
    # server by invoking its listen() method.
    #
    if CONFIG["server.raw"]:
        logging.debug("server: starting raw server... in progress")
        RAW_SERVER_EX.listen((":: 0.0.0.0", 12345), CONFIG["prefer_ipv6"], 0, "")
        logging.debug("server: starting raw server... complete")

    #
    # New-style modules are started just setting a
    # bunch of conf[] variables and then invoking
    # their run() method in order to kick them off.
    #
    if conf["server.negotiate"]:
        negotiate.run(POLLER, conf)

    if conf["server.bittorrent"]:
        conf["bittorrent.listen"] = True
        conf["bittorrent.negotiate"] = True
        bittorrent.run(POLLER, conf)

    if conf["server.speedtest"]:
        # conf['speedtest.listen'] = 1           # Not yet
        # conf['speedtest.negotiate'] = 1        # Not yet
        neubot.speedtest.wrapper.run(POLLER, conf)

    # Migrating from old style to new style
    if conf["server.rendezvous"]:
        # conf["rendezvous.listen"] = True       # Not yet
        neubot.rendezvous.server.run()

    #
    # Historically Neubot runs on port 9773 and
    # 8080 but we would like to switch to port 80
    # in the long term period, because it's rare
    # that they filter it.
    # OTOH it looks like it's not possible to
    # do that easily w/ M-Lab because the port
    # is already taken.
    #
    address = ":: 0.0.0.0"
    ports = (80, 8080, 9773)
    for port in ports:
        HTTP_SERVER.listen((address, port))

    #
    # Start server-side API for Nagios plugin
    # to query the state of the server.
    # functionalities.
    #
    if conf["server.sapi"]:
        server = ServerSideAPI(POLLER)
        server.configure(conf)
        HTTP_SERVER.register_child(server, "/sapi")

    #
    # Create localhost-only debug server
    #
    if CONFIG["server.debug"]:
        logging.info("server: Starting debug server at {127.0.0.1,::1}:9774")
        server = DebugAPI(POLLER)
        server.configure(conf)
        server.listen(("127.0.0.1 ::1", 9774))

    #
    # Go background and drop privileges,
    # then enter into the main loop.
    #
    if conf["server.daemonize"]:
        LOG.redirect()
        system.go_background()

    system.drop_privileges()
    POLLER.loop()
Ejemplo n.º 15
0
def main(args):
    """ Starts the server module """

    # By default, use mlab backend
    FILESYS.datadir_init()
    BACKEND.use_backend('mlab')

    #
    # Register descriptions in main() only so that
    # we don't advertise the name of knobs that aren't
    # relevant in the current context.
    #
    CONFIG.register_descriptions({
        "server.bittorrent": "Start up BitTorrent test and negotiate server",
        "server.daemonize": "Become a daemon and run in background",
        'server.debug': 'Run the localhost-only debug server',
        "server.negotiate": "Turn on negotiation infrastructure",
        "server.rendezvous": "Start up rendezvous server",
        "server.sapi": "Turn on Server-side API",
        "server.speedtest": "Start up Speedtest test and negotiate server",
    })

    common.main("server", "Neubot server-side component", args)
    conf = CONFIG.copy()

    #
    # Configure our global HTTP server and make
    # sure that we don't provide filesystem access
    # even by mistake.
    #
    conf["http.server.rootdir"] = ""
    HTTP_SERVER.configure(conf)

    #
    # New-style modules are started just setting a
    # bunch of conf[] variables and then invoking
    # their run() method in order to kick them off.
    #
    if conf["server.negotiate"]:
        negotiate.run(POLLER, conf)

    if conf["server.bittorrent"]:
        conf["bittorrent.listen"] = True
        conf["bittorrent.negotiate"] = True
        bittorrent.run(POLLER, conf)

    if conf['server.speedtest']:
        #conf['speedtest.listen'] = 1           # Not yet
        #conf['speedtest.negotiate'] = 1        # Not yet
        neubot.speedtest.wrapper.run(POLLER, conf)

    # Migrating from old style to new style
    if conf["server.rendezvous"]:
        #conf["rendezvous.listen"] = True       # Not yet
        neubot.rendezvous.server.run()

    #
    # Historically Neubot runs on port 9773 and
    # 8080 but we would like to switch to port 80
    # in the long term period, because it's rare
    # that they filter it.
    # OTOH it looks like it's not possible to
    # do that easily w/ M-Lab because the port
    # is already taken.
    #
    address = ""
    ports = (80, 8080, 9773)
    for port in ports:
        HTTP_SERVER.listen((address, port))

    #
    # Start server-side API for Nagios plugin
    # to query the state of the server.
    # functionalities.
    #
    if conf["server.sapi"]:
        server = ServerSideAPI(POLLER)
        server.configure(conf)
        HTTP_SERVER.register_child(server, "/sapi")

    #
    # Create localhost-only debug server
    #
    if CONFIG['server.debug']:
        LOG.info('server: Starting debug server at {127.0.0.1,::1}:9774')
        server = DebugAPI(POLLER)
        server.configure(conf)
        server.listen(('127.0.0.1 ::1', 9774))

    #
    # Go background and drop privileges,
    # then enter into the main loop.
    #
    if conf["server.daemonize"]:
        system.change_dir()
        system.go_background()
        system.write_pidfile()
        LOG.redirect()

    system.drop_privileges(LOG.error)
    POLLER.loop()
Ejemplo n.º 16
0
def main(args):
    """ Starts the server module """

    if not system.has_enough_privs():
        sys.exit('FATAL: you must be root')

    try:
        options, arguments = getopt.getopt(args[1:], 'A:b:D:dv')
    except getopt.error:
        sys.exit(USAGE)
    if arguments:
        sys.exit(USAGE)

    address = ':: 0.0.0.0'
    backend = 'mlab'
    for name, value in options:
        if name == '-A':
            address = value
        elif name == '-b':
            backend = value
        elif name == '-D':
            name, value = value.split('=', 1)
            if name not in VALID_MACROS:
                sys.exit(USAGE)
            if name != 'server.datadir':  # XXX
                value = int(value)
            SETTINGS[name] = value
        elif name == '-d':
            SETTINGS['server.daemonize'] = 0
        elif name == '-v':
            CONFIG['verbose'] = 1

    logging.debug('server: using backend: %s... in progress', backend)
    if backend == 'mlab':
        BACKEND.datadir_init(None, SETTINGS['server.datadir'])
        BACKEND.use_backend('mlab')
    elif backend == 'neubot':
        DATABASE.connect()
        BACKEND.use_backend('neubot')
    elif backend == 'volatile':
        BACKEND.use_backend('volatile')
    else:
        BACKEND.use_backend('null')
    logging.debug('server: using backend: %s... complete', backend)

    for name, value in SETTINGS.items():
        CONFIG[name] = value

    conf = CONFIG.copy()

    #
    # Configure our global HTTP server and make
    # sure that we don't provide filesystem access
    # even by mistake.
    #
    conf["http.server.rootdir"] = ""
    HTTP_SERVER.configure(conf)

    #
    # New-new style: don't bother with abstraction and start the f*****g
    # server by invoking its listen() method.
    #
    if CONFIG['server.raw']:
        logging.debug('server: starting raw server... in progress')
        RAW_SERVER_EX.listen((address, 12345),
          CONFIG['prefer_ipv6'], 0, '')
        logging.debug('server: starting raw server... complete')

    if conf['server.skype']:
        logging.debug('server: starting skype server... in progress')
        SKYPE_SERVER_EX.listen((":: 0.0.0.0", 45678),
            CONFIG['prefer_ipv6'], 0, '')
        logging.debug('server: starting skype server... complete')

    #
    # New-style modules are started just setting a
    # bunch of conf[] variables and then invoking
    # their run() method in order to kick them off.
    # This is now depricated in favor of the new-
    # new style described above.
    #

    if conf["server.negotiate"]:
        negotiate.run(POLLER, conf)

    if conf["server.bittorrent"]:
        conf["bittorrent.address"] = address
        conf["bittorrent.listen"] = True
        conf["bittorrent.negotiate"] = True
        bittorrent.run(POLLER, conf)

    if conf['server.speedtest']:
        #conf['speedtest.listen'] = 1           # Not yet
        #conf['speedtest.negotiate'] = 1        # Not yet
        neubot.speedtest.wrapper.run(POLLER, conf)

    # Migrating from old style to new style
    if conf["server.rendezvous"]:
        #conf["rendezvous.listen"] = True       # Not yet
        neubot.rendezvous.server.run()

    #
    # Historically Neubot runs on port 9773 and
    # 8080 but we would like to switch to port 80
    # in the long term period, because it's rare
    # that they filter it.
    # OTOH it looks like it's not possible to
    # do that easily w/ M-Lab because the port
    # is already taken.
    #
    ports = (80, 8080, 9773)
    for port in ports:
        HTTP_SERVER.listen((address, port))

    #
    # Start server-side API for Nagios plugin
    # to query the state of the server.
    # functionalities.
    #
    if conf["server.sapi"]:
        server = ServerSideAPI(POLLER)
        server.configure(conf)
        HTTP_SERVER.register_child(server, "/sapi")

    #
    # Create localhost-only debug server
    #
    if CONFIG['server.debug']:
        logging.info('server: Starting debug server at {127.0.0.1,::1}:9774')
        server = DebugAPI(POLLER)
        server.configure(conf)
        server.listen(('127.0.0.1 ::1', 9774))

    # Probe existing modules and ask them to attach to us
    utils_modules.modprobe(None, "server", {
        "http_server": HTTP_SERVER,
        "negotiate_server": NEGOTIATE_SERVER,
    })

    #
    # Go background and drop privileges,
    # then enter into the main loop.
    #
    if conf["server.daemonize"]:
        LOG.redirect()
        system.go_background()

    sigterm_handler = lambda signo, frame: POLLER.break_loop()
    signal.signal(signal.SIGTERM, sigterm_handler)

    logging.info('Neubot server -- starting up')
    system.drop_privileges()
    POLLER.loop()

    logging.info('Neubot server -- shutting down')
    utils_posix.remove_pidfile('/var/run/neubot.pid')
Ejemplo n.º 17
0
def main(args):
    """ Main function """
    try:
        options, arguments = getopt.getopt(args[1:], "6A:b:d:flnp:v")
    except getopt.error:
        sys.exit(USAGE)
    if arguments:
        sys.exit(USAGE)

    prefer_ipv6 = 0
    address = "127.0.0.1"
    backend = "volatile"
    datadir = None  # means: pick the default
    force = 0
    listen = 0
    negotiate = 1
    port = 80
    noisy = 0
    for name, value in options:
        if name == "-6":
            prefer_ipv6 = 1
        elif name == "-A":
            address = value
        elif name == "-b":
            backend = value
        elif name == "-d":
            datadir = value
        elif name == "-f":
            force = 1
        elif name == "-l":
            listen = 1
        elif name == "-n":
            negotiate = 0
        elif name == "-p":
            port = int(value)
        elif name == "-v":
            noisy = 1

    if noisy:
        log.set_verbose()

    conf = CONFIG.copy()

    BACKEND.use_backend(backend)
    BACKEND.datadir_init(None, datadir)

    if listen:
        if not negotiate:
            server = DASHServerSmpl(POLLER)
            server.configure(conf)
            server.listen((address, port))

        else:
            # Code adapted from neubot/server.py

            conf["http.server.rootdir"] = ""
            server = ServerHTTP(POLLER)
            server.configure(conf)
            server.listen((address, port))

            negotiate_server = NegotiateServer(POLLER)
            negotiate_server.configure(conf)
            server.register_child(negotiate_server, "/negotiate")
            server.register_child(negotiate_server, "/collect")

            dash_negotiate_server = DASHNegotiateServer()
            negotiate_server.register_module("dash", dash_negotiate_server)

            dash_server = DASHServerGlue(POLLER, dash_negotiate_server)
            dash_server.configure(conf)
            server.register_child(dash_server, "/dash")

    elif not force:
        result = runner_clnt.runner_client(CONFIG["agent.api.address"],
          CONFIG["agent.api.port"], CONFIG["verbose"], "dash")
        if result:
            sys.exit(0)
        logging.warning("dash: failed to contact Neubot; is Neubot running?")
        sys.exit(1)

    else:
        if negotiate:
            client = DASHNegotiateClient(POLLER)
        else:
            client = DASHClientSmpl(POLLER, None, DASH_RATES)
        client.configure(conf)
        client.connect((address, port))

    POLLER.loop()
Ejemplo n.º 18
0
def main(args):
    '''
     This function is invoked when the user wants
     to run precisely this module.
    '''

    try:
        options, arguments = getopt.getopt(args[1:], '6A:fp:v')
    except getopt.error:
        sys.exit('usage: neubot bittorrent [-6fv] [-A address] [-p port]')
    if arguments:
        sys.exit('usage: neubot bittorrent [-6fv] [-A address] [-p port]')

    prefer_ipv6 = 0
    address = 'master.neubot.org'
    force = 0
    port = 6881
    noisy = 0
    for name, value in options:
        if name == '-6':
            prefer_ipv6 = 1
        elif name == '-A':
            address = value
        elif name == '-f':
            force = 1
        elif name == '-p':
            port = int(value)
        elif name == '-v':
            noisy = 1

    if os.path.isfile(DATABASE.path):
        DATABASE.connect()
        CONFIG.merge_database(DATABASE.connection())
    else:
        logging.warning('bittorrent: database file is missing: %s',
                        DATABASE.path)
        BACKEND.use_backend('null')
    if noisy:
        log.set_verbose()

    config.register_descriptions()  # Needed?
    conf = CONFIG.copy()
    config.finalize_conf(conf)

    conf['bittorrent.address'] = address
    conf['bittorrent.port'] = port
    conf['prefer_ipv6'] = prefer_ipv6

    if not force:
        if runner_clnt.runner_client(conf["agent.api.address"],
                                     conf["agent.api.port"],
                                     CONFIG['verbose'],
                                     "bittorrent"):
            sys.exit(0)
        logging.warning(
          'bittorrent: failed to contact Neubot; is Neubot running?')
        sys.exit(1)

    logging.info('bittorrent: run the test in the local process context...')

    #
    # When we're connecting to a remote host to perform a test
    # we want Neubot to quit at the end of the test.  When this
    # happens the test code publishes the "testdone" event, so
    # here we prepare to intercept the event and break our main
    # loop.
    #
    NOTIFIER.subscribe("testdone", lambda event, ctx: POLLER.break_loop())
    run(POLLER, conf)
    POLLER.loop()