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
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()
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()
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
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()
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()
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()
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
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 {}
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")
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)
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()
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)
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()
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()
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')
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()
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()