Home | History | Annotate | Download | only in google
      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