1 #!/usr/bin/env python 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. 3 # Use of this source code is governed by a BSD-style license that can be 4 # found in the LICENSE file. 5 6 """Issue a series of GetHash requests to the SafeBrowsing servers and measure 7 the response times. 8 9 Usage: 10 11 $ ./gethash_timer.py --period=600 --samples=20 --output=resp.csv 12 13 --period (or -p): The amount of time (in seconds) to wait between GetHash 14 requests. Using a value of more than 300 (5 minutes) to 15 include the effect of DNS. 16 17 --samples (or -s): The number of requests to issue. If this parameter is not 18 specified, the test will run indefinitely. 19 20 --output (or -o): The path to a file where the output will be written in 21 CSV format: sample_number,response_code,elapsed_time_ms 22 """ 23 24 import getopt 25 import httplib 26 import sys 27 import time 28 29 _GETHASH_HOST = 'safebrowsing.clients.google.com' 30 _GETHASH_REQUEST = ( 31 '/safebrowsing/gethash?client=googleclient&appver=1.0&pver=2.1') 32 33 # Global logging file handle. 34 g_file_handle = None 35 36 37 def IssueGetHash(prefix): 38 '''Issue one GetHash request to the safebrowsing servers. 39 Args: 40 prefix: A 4 byte value to look up on the server. 41 Returns: 42 The HTTP response code for the GetHash request. 43 ''' 44 body = '4:4\n' + prefix 45 h = httplib.HTTPConnection(_GETHASH_HOST) 46 h.putrequest('POST', _GETHASH_REQUEST) 47 h.putheader('content-length', str(len(body))) 48 h.endheaders() 49 h.send(body) 50 response_code = h.getresponse().status 51 h.close() 52 return response_code 53 54 55 def TimedGetHash(prefix): 56 '''Measure the amount of time it takes to receive a GetHash response. 57 Args: 58 prefix: A 4 byte value to look up on the the server. 59 Returns: 60 A tuple of HTTP resonse code and the response time (in milliseconds). 61 ''' 62 start = time.time() 63 response_code = IssueGetHash(prefix) 64 return response_code, (time.time() - start) * 1000 65 66 67 def RunTimedGetHash(period, samples=None): 68 '''Runs an experiment to measure the amount of time it takes to receive 69 multiple responses from the GetHash servers. 70 71 Args: 72 period: A floating point value that indicates (in seconds) the delay 73 between requests. 74 samples: An integer value indicating the number of requests to make. 75 If 'None', the test continues indefinitely. 76 Returns: 77 None. 78 ''' 79 global g_file_handle 80 prefix = '\x50\x61\x75\x6c' 81 sample_count = 1 82 while True: 83 response_code, elapsed_time = TimedGetHash(prefix) 84 LogResponse(sample_count, response_code, elapsed_time) 85 sample_count += 1 86 if samples is not None and sample_count == samples: 87 break 88 time.sleep(period) 89 90 91 def LogResponse(sample_count, response_code, elapsed_time): 92 '''Output the response for one GetHash query. 93 Args: 94 sample_count: The current sample number. 95 response_code: The HTTP response code for the GetHash request. 96 elapsed_time: The round-trip time (in milliseconds) for the 97 GetHash request. 98 Returns: 99 None. 100 ''' 101 global g_file_handle 102 output_list = (sample_count, response_code, elapsed_time) 103 print 'Request: %d, status: %d, elapsed time: %f ms' % output_list 104 if g_file_handle is not None: 105 g_file_handle.write(('%d,%d,%f' % output_list) + '\n') 106 g_file_handle.flush() 107 108 109 def SetupOutputFile(file_name): 110 '''Open a file for logging results. 111 Args: 112 file_name: A path to a file to store the output. 113 Returns: 114 None. 115 ''' 116 global g_file_handle 117 g_file_handle = open(file_name, 'w') 118 119 120 def main(): 121 period = 10 122 samples = None 123 124 options, args = getopt.getopt(sys.argv[1:], 125 's:p:o:', 126 ['samples=', 'period=', 'output=']) 127 for option, value in options: 128 if option == '-s' or option == '--samples': 129 samples = int(value) 130 elif option == '-p' or option == '--period': 131 period = float(value) 132 elif option == '-o' or option == '--output': 133 file_name = value 134 else: 135 print 'Bad option: %s' % option 136 return 1 137 try: 138 print 'Starting Timed GetHash ----------' 139 SetupOutputFile(file_name) 140 RunTimedGetHash(period, samples) 141 except KeyboardInterrupt: 142 pass 143 144 print 'Timed GetHash complete ----------' 145 g_file_handle.close() 146 147 148 if __name__ == '__main__': 149 sys.exit(main()) 150