# Copyright (c) 2012 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.

"""A "Test Server Spawner" that handles killing/stopping per-test test servers.

It's used to accept requests from the device to spawn and kill instances of the
chrome test server on the host.
"""

import BaseHTTPServer
import json
import logging
import os
import select
import struct
import subprocess
import threading
import time
import urlparse

import constants
from forwarder import Forwarder
import ports


# Path that are needed to import necessary modules when running testserver.py.
os.environ['PYTHONPATH'] = os.environ.get('PYTHONPATH', '') + ':%s:%s:%s:%s' % (
    os.path.join(constants.CHROME_DIR, 'third_party'),
    os.path.join(constants.CHROME_DIR, 'third_party', 'tlslite'),
    os.path.join(constants.CHROME_DIR, 'third_party', 'pyftpdlib', 'src'),
    os.path.join(constants.CHROME_DIR, 'net', 'tools', 'testserver'))


SERVER_TYPES = {
    'http': '',
    'ftp': '-f',
    'sync': '--sync',
    'tcpecho': '--tcp-echo',
    'udpecho': '--udp-echo',
}


# The timeout (in seconds) of starting up the Python test server.
TEST_SERVER_STARTUP_TIMEOUT = 10


def _CheckPortStatus(port, expected_status):
  """Returns True if port has expected_status.

  Args:
    port: the port number.
    expected_status: boolean of expected status.

  Returns:
    Returns True if the status is expected. Otherwise returns False.
  """
  for timeout in range(1, 5):
    if ports.IsHostPortUsed(port) == expected_status:
      return True
    time.sleep(timeout)
  return False


def _GetServerTypeCommandLine(server_type):
  """Returns the command-line by the given server type.

  Args:
    server_type: the server type to be used (e.g. 'http').

  Returns:
    A string containing the command-line argument.
  """
  if server_type not in SERVER_TYPES:
    raise NotImplementedError('Unknown server type: %s' % server_type)
  if server_type == 'udpecho':
    raise Exception('Please do not run UDP echo tests because we do not have '
                    'a UDP forwarder tool.')
  return SERVER_TYPES[server_type]


class TestServerThread(threading.Thread):
  """A thread to run the test server in a separate process."""

  def __init__(self, ready_event, arguments, adb, tool, build_type):
    """Initialize TestServerThread with the following argument.

    Args:
      ready_event: event which will be set when the test server is ready.
      arguments: dictionary of arguments to run the test server.
      adb: instance of AndroidCommands.
      tool: instance of runtime error detection tool.
      build_type: 'Release' or 'Debug'.
    """
    threading.Thread.__init__(self)
    self.wait_event = threading.Event()
    self.stop_flag = False
    self.ready_event = ready_event
    self.ready_event.clear()
    self.arguments = arguments
    self.adb = adb
    self.tool = tool
    self.test_server_process = None
    self.is_ready = False
    self.host_port = self.arguments['port']
    assert isinstance(self.host_port, int)
    self._test_server_forwarder = None
    # The forwarder device port now is dynamically allocated.
    self.forwarder_device_port = 0
    # Anonymous pipe in order to get port info from test server.
    self.pipe_in = None
    self.pipe_out = None
    self.command_line = []
    self.build_type = build_type

  def _WaitToStartAndGetPortFromTestServer(self):
    """Waits for the Python test server to start and gets the port it is using.

    The port information is passed by the Python test server with a pipe given
    by self.pipe_out. It is written as a result to |self.host_port|.

    Returns:
      Whether the port used by the test server was successfully fetched.
    """
    assert self.host_port == 0 and self.pipe_out and self.pipe_in
    (in_fds, _, _) = select.select([self.pipe_in, ], [], [],
                                   TEST_SERVER_STARTUP_TIMEOUT)
    if len(in_fds) == 0:
      logging.error('Failed to wait to the Python test server to be started.')
      return False
    # First read the data length as an unsigned 4-byte value.  This
    # is _not_ using network byte ordering since the Python test server packs
    # size as native byte order and all Chromium platforms so far are
    # configured to use little-endian.
    # TODO(jnd): Change the Python test server and local_test_server_*.cc to
    # use a unified byte order (either big-endian or little-endian).
    data_length = os.read(self.pipe_in, struct.calcsize('=L'))
    if data_length:
      (data_length,) = struct.unpack('=L', data_length)
      assert data_length
    if not data_length:
      logging.error('Failed to get length of server data.')
      return False
    port_json = os.read(self.pipe_in, data_length)
    if not port_json:
      logging.error('Failed to get server data.')
      return False
    logging.info('Got port json data: %s', port_json)
    port_json = json.loads(port_json)
    if port_json.has_key('port') and isinstance(port_json['port'], int):
      self.host_port = port_json['port']
      return _CheckPortStatus(self.host_port, True)
    logging.error('Failed to get port information from the server data.')
    return False

  def _GenerateCommandLineArguments(self):
    """Generates the command line to run the test server.

    Note that all options are processed by following the definitions in
    testserver.py.
    """
    if self.command_line:
      return
    # The following arguments must exist.
    type_cmd = _GetServerTypeCommandLine(self.arguments['server-type'])
    if type_cmd:
      self.command_line.append(type_cmd)
    self.command_line.append('--port=%d' % self.host_port)
    # Use a pipe to get the port given by the instance of Python test server
    # if the test does not specify the port.
    if self.host_port == 0:
      (self.pipe_in, self.pipe_out) = os.pipe()
      self.command_line.append('--startup-pipe=%d' % self.pipe_out)
    self.command_line.append('--host=%s' % self.arguments['host'])
    data_dir = self.arguments['data-dir'] or 'chrome/test/data'
    if not os.path.isabs(data_dir):
      data_dir = os.path.join(constants.CHROME_DIR, data_dir)
    self.command_line.append('--data-dir=%s' % data_dir)
    # The following arguments are optional depending on the individual test.
    if self.arguments.has_key('log-to-console'):
      self.command_line.append('--log-to-console')
    if self.arguments.has_key('auth-token'):
      self.command_line.append('--auth-token=%s' % self.arguments['auth-token'])
    if self.arguments.has_key('https'):
      self.command_line.append('--https')
      if self.arguments.has_key('cert-and-key-file'):
        self.command_line.append('--cert-and-key-file=%s' % os.path.join(
            constants.CHROME_DIR, self.arguments['cert-and-key-file']))
      if self.arguments.has_key('ocsp'):
        self.command_line.append('--ocsp=%s' % self.arguments['ocsp'])
      if self.arguments.has_key('https-record-resume'):
        self.command_line.append('--https-record-resume')
      if self.arguments.has_key('ssl-client-auth'):
        self.command_line.append('--ssl-client-auth')
      if self.arguments.has_key('tls-intolerant'):
        self.command_line.append('--tls-intolerant=%s' %
                                 self.arguments['tls-intolerant'])
      if self.arguments.has_key('ssl-client-ca'):
        for ca in self.arguments['ssl-client-ca']:
          self.command_line.append('--ssl-client-ca=%s' %
                                   os.path.join(constants.CHROME_DIR, ca))
      if self.arguments.has_key('ssl-bulk-cipher'):
        for bulk_cipher in self.arguments['ssl-bulk-cipher']:
          self.command_line.append('--ssl-bulk-cipher=%s' % bulk_cipher)

  def run(self):
    logging.info('Start running the thread!')
    self.wait_event.clear()
    self._GenerateCommandLineArguments()
    command = [os.path.join(constants.CHROME_DIR, 'net', 'tools',
                            'testserver', 'testserver.py')] + self.command_line
    logging.info('Running: %s', command)
    self.process = subprocess.Popen(command)
    if self.process:
      if self.pipe_out:
        self.is_ready = self._WaitToStartAndGetPortFromTestServer()
      else:
        self.is_ready = _CheckPortStatus(self.host_port, True)
    if self.is_ready:
      self._test_server_forwarder = Forwarder(self.adb, self.build_type)
      self._test_server_forwarder.Run(
          [(0, self.host_port)], self.tool, '127.0.0.1')
      # Check whether the forwarder is ready on the device.
      self.is_ready = False
      device_port = self._test_server_forwarder.DevicePortForHostPort(
          self.host_port)
      if device_port:
        for timeout in range(1, 5):
          if ports.IsDevicePortUsed(self.adb, device_port, 'LISTEN'):
            self.is_ready = True
            self.forwarder_device_port = device_port
            break
          time.sleep(timeout)
    # Wake up the request handler thread.
    self.ready_event.set()
    # Keep thread running until Stop() gets called.
    while not self.stop_flag:
      time.sleep(1)
    if self.process.poll() is None:
      self.process.kill()
    if self._test_server_forwarder:
      self._test_server_forwarder.Close()
    self.process = None
    self.is_ready = False
    if self.pipe_out:
      os.close(self.pipe_in)
      os.close(self.pipe_out)
      self.pipe_in = None
      self.pipe_out = None
    logging.info('Test-server has died.')
    self.wait_event.set()

  def Stop(self):
    """Blocks until the loop has finished.

    Note that this must be called in another thread.
    """
    if not self.process:
      return
    self.stop_flag = True
    self.wait_event.wait()


class SpawningServerRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
  """A handler used to process http GET/POST request."""

  def _SendResponse(self, response_code, response_reason, additional_headers,
                    contents):
    """Generates a response sent to the client from the provided parameters.

    Args:
      response_code: number of the response status.
      response_reason: string of reason description of the response.
      additional_headers: dict of additional headers. Each key is the name of
                          the header, each value is the content of the header.
      contents: string of the contents we want to send to client.
    """
    self.send_response(response_code, response_reason)
    self.send_header('Content-Type', 'text/html')
    # Specify the content-length as without it the http(s) response will not
    # be completed properly (and the browser keeps expecting data).
    self.send_header('Content-Length', len(contents))
    for header_name in additional_headers:
      self.send_header(header_name, additional_headers[header_name])
    self.end_headers()
    self.wfile.write(contents)
    self.wfile.flush()

  def _StartTestServer(self):
    """Starts the test server thread."""
    logging.info('Handling request to spawn a test server.')
    content_type = self.headers.getheader('content-type')
    if content_type != 'application/json':
      raise Exception('Bad content-type for start request.')
    content_length = self.headers.getheader('content-length')
    if not content_length:
      content_length = 0
    try:
      content_length = int(content_length)
    except:
      raise Exception('Bad content-length for start request.')
    logging.info(content_length)
    test_server_argument_json = self.rfile.read(content_length)
    logging.info(test_server_argument_json)
    assert not self.server.test_server_instance
    ready_event = threading.Event()
    self.server.test_server_instance = TestServerThread(
        ready_event,
        json.loads(test_server_argument_json),
        self.server.adb,
        self.server.tool,
        self.server.build_type)
    self.server.test_server_instance.setDaemon(True)
    self.server.test_server_instance.start()
    ready_event.wait()
    if self.server.test_server_instance.is_ready:
      self._SendResponse(200, 'OK', {}, json.dumps(
          {'port': self.server.test_server_instance.forwarder_device_port,
           'message': 'started'}))
      logging.info('Test server is running on port: %d.',
                   self.server.test_server_instance.host_port)
    else:
      self.server.test_server_instance.Stop()
      self.server.test_server_instance = None
      self._SendResponse(500, 'Test Server Error.', {}, '')
      logging.info('Encounter problem during starting a test server.')

  def _KillTestServer(self):
    """Stops the test server instance."""
    # There should only ever be one test server at a time. This may do the
    # wrong thing if we try and start multiple test servers.
    if not self.server.test_server_instance:
      return
    port = self.server.test_server_instance.host_port
    logging.info('Handling request to kill a test server on port: %d.', port)
    self.server.test_server_instance.Stop()
    # Make sure the status of test server is correct before sending response.
    if _CheckPortStatus(port, False):
      self._SendResponse(200, 'OK', {}, 'killed')
      logging.info('Test server on port %d is killed', port)
    else:
      self._SendResponse(500, 'Test Server Error.', {}, '')
      logging.info('Encounter problem during killing a test server.')
    self.server.test_server_instance = None

  def do_POST(self):
    parsed_path = urlparse.urlparse(self.path)
    action = parsed_path.path
    logging.info('Action for POST method is: %s.', action)
    if action == '/start':
      self._StartTestServer()
    else:
      self._SendResponse(400, 'Unknown request.', {}, '')
      logging.info('Encounter unknown request: %s.', action)

  def do_GET(self):
    parsed_path = urlparse.urlparse(self.path)
    action = parsed_path.path
    params = urlparse.parse_qs(parsed_path.query, keep_blank_values=1)
    logging.info('Action for GET method is: %s.', action)
    for param in params:
      logging.info('%s=%s', param, params[param][0])
    if action == '/kill':
      self._KillTestServer()
    elif action == '/ping':
      # The ping handler is used to check whether the spawner server is ready
      # to serve the requests. We don't need to test the status of the test
      # server when handling ping request.
      self._SendResponse(200, 'OK', {}, 'ready')
      logging.info('Handled ping request and sent response.')
    else:
      self._SendResponse(400, 'Unknown request', {}, '')
      logging.info('Encounter unknown request: %s.', action)


class SpawningServer(object):
  """The class used to start/stop a http server."""

  def __init__(self, test_server_spawner_port, adb, tool, build_type):
    logging.info('Creating new spawner on port: %d.', test_server_spawner_port)
    self.server = BaseHTTPServer.HTTPServer(('', test_server_spawner_port),
                                            SpawningServerRequestHandler)
    self.port = test_server_spawner_port
    self.server.adb = adb
    self.server.tool = tool
    self.server.test_server_instance = None
    self.server.build_type = build_type

  def _Listen(self):
    logging.info('Starting test server spawner')
    self.server.serve_forever()

  def Start(self):
    listener_thread = threading.Thread(target=self._Listen)
    listener_thread.setDaemon(True)
    listener_thread.start()
    time.sleep(1)

  def Stop(self):
    if self.server.test_server_instance:
      self.server.test_server_instance.Stop()
    self.server.shutdown()
