15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/usr/bin/env python 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2011 The Chromium Authors. All rights reserved. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file. 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""Issue a series of GetHash requests to the SafeBrowsing servers and measure 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)the response times. 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Usage: 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) $ ./gethash_timer.py --period=600 --samples=20 --output=resp.csv 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --period (or -p): The amount of time (in seconds) to wait between GetHash 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) requests. Using a value of more than 300 (5 minutes) to 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) include the effect of DNS. 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --samples (or -s): The number of requests to issue. If this parameter is not 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) specified, the test will run indefinitely. 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --output (or -o): The path to a file where the output will be written in 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CSV format: sample_number,response_code,elapsed_time_ms 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)""" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import getopt 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import httplib 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import sys 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import time 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_GETHASH_HOST = 'safebrowsing.clients.google.com' 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_GETHASH_REQUEST = ( 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '/safebrowsing/gethash?client=googleclient&appver=1.0&pver=2.1') 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Global logging file handle. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)g_file_handle = None 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def IssueGetHash(prefix): 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '''Issue one GetHash request to the safebrowsing servers. 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Args: 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefix: A 4 byte value to look up on the server. 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Returns: 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) The HTTP response code for the GetHash request. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) body = '4:4\n' + prefix 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) h = httplib.HTTPConnection(_GETHASH_HOST) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) h.putrequest('POST', _GETHASH_REQUEST) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) h.putheader('content-length', str(len(body))) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) h.endheaders() 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) h.send(body) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_code = h.getresponse().status 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) h.close() 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return response_code 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def TimedGetHash(prefix): 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '''Measure the amount of time it takes to receive a GetHash response. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Args: 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefix: A 4 byte value to look up on the the server. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Returns: 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) A tuple of HTTP resonse code and the response time (in milliseconds). 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start = time.time() 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_code = IssueGetHash(prefix) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return response_code, (time.time() - start) * 1000 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def RunTimedGetHash(period, samples=None): 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '''Runs an experiment to measure the amount of time it takes to receive 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) multiple responses from the GetHash servers. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Args: 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) period: A floating point value that indicates (in seconds) the delay 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) between requests. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) samples: An integer value indicating the number of requests to make. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) If 'None', the test continues indefinitely. 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Returns: 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) None. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global g_file_handle 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefix = '\x50\x61\x75\x6c' 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sample_count = 1 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while True: 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_code, elapsed_time = TimedGetHash(prefix) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogResponse(sample_count, response_code, elapsed_time) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sample_count += 1 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if samples is not None and sample_count == samples: 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time.sleep(period) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def LogResponse(sample_count, response_code, elapsed_time): 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '''Output the response for one GetHash query. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Args: 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sample_count: The current sample number. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_code: The HTTP response code for the GetHash request. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elapsed_time: The round-trip time (in milliseconds) for the 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetHash request. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Returns: 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) None. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global g_file_handle 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output_list = (sample_count, response_code, elapsed_time) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print 'Request: %d, status: %d, elapsed time: %f ms' % output_list 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if g_file_handle is not None: 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_file_handle.write(('%d,%d,%f' % output_list) + '\n') 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_file_handle.flush() 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def SetupOutputFile(file_name): 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '''Open a file for logging results. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Args: 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_name: A path to a file to store the output. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Returns: 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) None. 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global g_file_handle 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_file_handle = open(file_name, 'w') 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def main(): 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) period = 10 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) samples = None 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options, args = getopt.getopt(sys.argv[1:], 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 's:p:o:', 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ['samples=', 'period=', 'output=']) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for option, value in options: 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if option == '-s' or option == '--samples': 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) samples = int(value) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elif option == '-p' or option == '--period': 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) period = float(value) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elif option == '-o' or option == '--output': 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_name = value 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print 'Bad option: %s' % option 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try: 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print 'Starting Timed GetHash ----------' 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetupOutputFile(file_name) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunTimedGetHash(period, samples) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) except KeyboardInterrupt: 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pass 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print 'Timed GetHash complete ----------' 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_file_handle.close() 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if __name__ == '__main__': 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys.exit(main()) 150