| #!/usr/bin/env python | |
| # Copyright 2011 The Chromium Authors | |
| # Use of this source code is governed by a BSD-style license that can be | |
| # found in the LICENSE file. | |
| """Issue a series of GetHash requests to the SafeBrowsing servers and measure | |
| the response times. | |
| Usage: | |
| $ ./gethash_timer.py --period=600 --samples=20 --output=resp.csv | |
| --period (or -p): The amount of time (in seconds) to wait between GetHash | |
| requests. Using a value of more than 300 (5 minutes) to | |
| include the effect of DNS. | |
| --samples (or -s): The number of requests to issue. If this parameter is not | |
| specified, the test will run indefinitely. | |
| --output (or -o): The path to a file where the output will be written in | |
| CSV format: sample_number,response_code,elapsed_time_ms | |
| """ | |
| from __future__ import print_function | |
| import getopt | |
| import httplib | |
| import sys | |
| import time | |
| _GETHASH_HOST = 'safebrowsing.clients.google.com' | |
| _GETHASH_REQUEST = ( | |
| '/safebrowsing/gethash?client=googleclient&appver=1.0&pver=2.1' | |
| ) | |
| # Global logging file handle. | |
| g_file_handle = None | |
| def IssueGetHash(prefix): | |
| '''Issue one GetHash request to the safebrowsing servers. | |
| Args: | |
| prefix: A 4 byte value to look up on the server. | |
| Returns: | |
| The HTTP response code for the GetHash request. | |
| ''' | |
| body = '4:4\n' + prefix | |
| h = httplib.HTTPConnection(_GETHASH_HOST) | |
| h.putrequest('POST', _GETHASH_REQUEST) | |
| h.putheader('content-length', str(len(body))) | |
| h.endheaders() | |
| h.send(body) | |
| response_code = h.getresponse().status | |
| h.close() | |
| return response_code | |
| def TimedGetHash(prefix): | |
| '''Measure the amount of time it takes to receive a GetHash response. | |
| Args: | |
| prefix: A 4 byte value to look up on the the server. | |
| Returns: | |
| A tuple of HTTP resonse code and the response time (in milliseconds). | |
| ''' | |
| start = time.time() | |
| response_code = IssueGetHash(prefix) | |
| return response_code, (time.time() - start) * 1000 | |
| def RunTimedGetHash(period, samples=None): | |
| '''Runs an experiment to measure the amount of time it takes to receive | |
| multiple responses from the GetHash servers. | |
| Args: | |
| period: A floating point value that indicates (in seconds) the delay | |
| between requests. | |
| samples: An integer value indicating the number of requests to make. | |
| If 'None', the test continues indefinitely. | |
| Returns: | |
| None. | |
| ''' | |
| global g_file_handle | |
| prefix = '\x50\x61\x75\x6c' | |
| sample_count = 1 | |
| while True: | |
| response_code, elapsed_time = TimedGetHash(prefix) | |
| LogResponse(sample_count, response_code, elapsed_time) | |
| sample_count += 1 | |
| if samples is not None and sample_count == samples: | |
| break | |
| time.sleep(period) | |
| def LogResponse(sample_count, response_code, elapsed_time): | |
| '''Output the response for one GetHash query. | |
| Args: | |
| sample_count: The current sample number. | |
| response_code: The HTTP response code for the GetHash request. | |
| elapsed_time: The round-trip time (in milliseconds) for the | |
| GetHash request. | |
| Returns: | |
| None. | |
| ''' | |
| global g_file_handle | |
| output_list = (sample_count, response_code, elapsed_time) | |
| print('Request: %d, status: %d, elapsed time: %f ms' % output_list) | |
| if g_file_handle is not None: | |
| g_file_handle.write(('%d,%d,%f' % output_list) + '\n') | |
| g_file_handle.flush() | |
| def SetupOutputFile(file_name): | |
| '''Open a file for logging results. | |
| Args: | |
| file_name: A path to a file to store the output. | |
| Returns: | |
| None. | |
| ''' | |
| global g_file_handle | |
| g_file_handle = open(file_name, 'w') | |
| def main(): | |
| period = 10 | |
| samples = None | |
| options, args = getopt.getopt( | |
| sys.argv[1:], 's:p:o:', ['samples=', 'period=', 'output='] | |
| ) | |
| for option, value in options: | |
| if option == '-s' or option == '--samples': | |
| samples = int(value) | |
| elif option == '-p' or option == '--period': | |
| period = float(value) | |
| elif option == '-o' or option == '--output': | |
| file_name = value | |
| else: | |
| print('Bad option: %s' % option) | |
| return 1 | |
| try: | |
| print('Starting Timed GetHash ----------') | |
| SetupOutputFile(file_name) | |
| RunTimedGetHash(period, samples) | |
| except KeyboardInterrupt: | |
| pass | |
| print('Timed GetHash complete ----------') | |
| g_file_handle.close() | |
| if __name__ == '__main__': | |
| sys.exit(main()) |