From 0fbfdf7ea9a8650daea1a173bee28ff04f991700 Mon Sep 17 00:00:00 2001 From: Dubravko Penezic Date: Mon, 23 Mar 2015 22:43:23 +0100 Subject: [PATCH] Gather information about configuration from multiple URLs Patch add functionality for gathering informatio about configuration and server list from multiple URLs. URLs prefix is defined via global variables. Author Dubravko Penezic --- speedtest_cli.py | 97 ++++++++++++++++++++++++++++++------------------ 1 file changed, 61 insertions(+), 36 deletions(-) diff --git a/speedtest_cli.py b/speedtest_cli.py index 2beeb35..8bc688f 100755 --- a/speedtest_cli.py +++ b/speedtest_cli.py @@ -34,6 +34,13 @@ shutdown_event = None # Used for bound_interface socket_socket = socket.socket +# Config server URL prefix +conf_server_urls_prefix = [ + 'http://www.speedtest.net/', + 'https://www.speedtest.net/', + 'http://c.speedtest.net/', + ] + try: import xml.etree.cElementTree as ET except ImportError: @@ -145,6 +152,12 @@ class SpeedtestCliServerListError(Exception): """ +class SpeedtestConfigDataError(Exception): + """Internal Exception class used to indicate to move on to the next + URL for retrieving speedtest.net configuration details + + """ + def bound_socket(*args, **kwargs): """Bind socket to a specified source IP address""" @@ -339,40 +352,55 @@ def getConfig(): """Download the speedtest.net configuration and return only the data we are interested in """ + + config = {} + for url_prefix in conf_server_urls_prefix: + url = url_prefix+'speedtest-config.php' + try: + request = build_request(url) + uh = catch_request(request) + if uh is False: + raise SpeedtestConfigDataError + configxml = [] + while 1: + configxml.append(uh.read(10240)) + if len(configxml[-1]) == 0: + break + if int(uh.code) != 200: + uh.close + raise SpeedtestConfigDataError + uh.close() + try: + try: + root = ET.fromstring(''.encode().join(configxml)) + config = { + 'client': root.find('client').attrib, + 'times': root.find('times').attrib, + 'download': root.find('download').attrib, + 'upload': root.find('upload').attrib} + except AttributeError: # Python3 branch + root = DOM.parseString(''.join(configxml)) + config = { + 'client': getAttributesByTagName(root, 'client'), + 'times': getAttributesByTagName(root, 'times'), + 'download': getAttributesByTagName(root, 'download'), + 'upload': getAttributesByTagName(root, 'upload')} + except SyntaxError: + raise SpeedtestConfigDataError + del root + del configxml + except SpeedtestConfigDataError: + continue - request = build_request('https://www.speedtest.net/speedtest-config.php') - uh = catch_request(request) - if uh is False: + # We were able to fetch and parse the list of speedtest.net servers + if config: + break + + if not config: print_('Could not retrieve speedtest.net configuration') sys.exit(1) - configxml = [] - while 1: - configxml.append(uh.read(10240)) - if len(configxml[-1]) == 0: - break - if int(uh.code) != 200: - return None - uh.close() - try: - try: - root = ET.fromstring(''.encode().join(configxml)) - config = { - 'client': root.find('client').attrib, - 'times': root.find('times').attrib, - 'download': root.find('download').attrib, - 'upload': root.find('upload').attrib} - except AttributeError: # Python3 branch - root = DOM.parseString(''.join(configxml)) - config = { - 'client': getAttributesByTagName(root, 'client'), - 'times': getAttributesByTagName(root, 'times'), - 'download': getAttributesByTagName(root, 'download'), - 'upload': getAttributesByTagName(root, 'upload')} - except SyntaxError: - print_('Failed to parse speedtest.net configuration') - sys.exit(1) - del root - del configxml + + return config @@ -381,12 +409,9 @@ def closestServers(client, all=False): distance """ - urls = [ - 'https://www.speedtest.net/speedtest-servers-static.php', - 'http://c.speedtest.net/speedtest-servers-static.php', - ] servers = {} - for url in urls: + for url_prefix in conf_server_urls_prefix: + url = url_prefix+'speedtest-servers-static.php' try: request = build_request(url) uh = catch_request(request)