Home | History | Annotate | Download | only in mod_pywebsocket
      1 # Copyright 2014 Google Inc. All rights reserved.
      2 #
      3 # Use of this source code is governed by a BSD-style
      4 # license that can be found in the COPYING file or at
      5 # https://developers.google.com/open-source/licenses/bsd
      6 
      7 
      8 from mod_pywebsocket import util
      9 
     10 
     11 class XHRBenchmarkHandler(object):
     12     def __init__(self, headers, rfile, wfile):
     13         self._logger = util.get_class_logger(self)
     14 
     15         self.headers = headers
     16         self.rfile = rfile
     17         self.wfile = wfile
     18 
     19     def do_send(self):
     20         content_length = int(self.headers.getheader('Content-Length'))
     21 
     22         self._logger.debug('Requested to receive %s bytes', content_length)
     23 
     24         RECEIVE_BLOCK_SIZE = 1024 * 1024
     25 
     26         bytes_to_receive = content_length
     27         while bytes_to_receive > 0:
     28             bytes_to_receive_in_this_loop = bytes_to_receive
     29             if bytes_to_receive_in_this_loop > RECEIVE_BLOCK_SIZE:
     30                 bytes_to_receive_in_this_loop = RECEIVE_BLOCK_SIZE
     31             received_data = self.rfile.read(bytes_to_receive_in_this_loop)
     32             for c in received_data:
     33                 if c != 'a':
     34                     self._logger.debug('Request body verification failed')
     35                     return
     36             bytes_to_receive -= len(received_data)
     37         if bytes_to_receive < 0:
     38             self._logger.debug('Received %d more bytes than expected' %
     39                                (-bytes_to_receive))
     40             return
     41 
     42         # Return the number of received bytes back to the client.
     43         response_body = '%d' % content_length
     44         self.wfile.write(
     45             'HTTP/1.1 200 OK\r\n'
     46             'Content-Type: text/html\r\n'
     47             'Content-Length: %d\r\n'
     48             '\r\n%s' % (len(response_body), response_body))
     49         self.wfile.flush()
     50 
     51     def do_receive(self):
     52         content_length = int(self.headers.getheader('Content-Length'))
     53         request_body = self.rfile.read(content_length)
     54 
     55         request_array = request_body.split(' ')
     56         if len(request_array) < 2:
     57             self._logger.debug('Malformed request body: %r', request_body)
     58             return
     59 
     60         # Parse the size parameter.
     61         bytes_to_send = request_array[0]
     62         try:
     63             bytes_to_send = int(bytes_to_send)
     64         except ValueError, e:
     65             self._logger.debug('Malformed size parameter: %r', bytes_to_send)
     66             return
     67         self._logger.debug('Requested to send %s bytes', bytes_to_send)
     68 
     69         # Parse the transfer encoding parameter.
     70         chunked_mode = False
     71         mode_parameter = request_array[1]
     72         if mode_parameter == 'chunked':
     73             self._logger.debug('Requested chunked transfer encoding')
     74             chunked_mode = True
     75         elif mode_parameter != 'none':
     76             self._logger.debug('Invalid mode parameter: %r', mode_parameter)
     77             return
     78 
     79         # Write a header
     80         response_header = (
     81             'HTTP/1.1 200 OK\r\n'
     82             'Content-Type: application/octet-stream\r\n')
     83         if chunked_mode:
     84             response_header += 'Transfer-Encoding: chunked\r\n\r\n'
     85         else:
     86             response_header += (
     87                 'Content-Length: %d\r\n\r\n' % bytes_to_send)
     88         self.wfile.write(response_header)
     89         self.wfile.flush()
     90 
     91         # Write a body
     92         SEND_BLOCK_SIZE = 1024 * 1024
     93 
     94         while bytes_to_send > 0:
     95             bytes_to_send_in_this_loop = bytes_to_send
     96             if bytes_to_send_in_this_loop > SEND_BLOCK_SIZE:
     97                 bytes_to_send_in_this_loop = SEND_BLOCK_SIZE
     98 
     99             if chunked_mode:
    100                 self.wfile.write('%x\r\n' % bytes_to_send_in_this_loop)
    101             self.wfile.write('a' * bytes_to_send_in_this_loop)
    102             if chunked_mode:
    103                 self.wfile.write('\r\n')
    104             self.wfile.flush()
    105 
    106             bytes_to_send -= bytes_to_send_in_this_loop
    107 
    108         if chunked_mode:
    109             self.wfile.write('0\r\n\r\n')
    110             self.wfile.flush()
    111