150 lines
4.3 KiB
Python
150 lines
4.3 KiB
Python
|
#!/usr/bin/env python
|
||
|
# Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
||
|
# 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
|
||
|
"""
|
||
|
|
||
|
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())
|