# Copyright 2013 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.

import BaseHTTPServer
import errno
import json
import optparse
import os
import re
import socket
import SocketServer
import struct
import sys
import warnings

import tlslite.errors

# Ignore deprecation warnings, they make our output more cluttered.
warnings.filterwarnings("ignore", category=DeprecationWarning)

if sys.platform == 'win32':
  import msvcrt

# Using debug() seems to cause hangs on XP: see http://crbug.com/64515.
debug_output = sys.stderr
def debug(string):
  debug_output.write(string + "\n")
  debug_output.flush()


class Error(Exception):
  """Error class for this module."""


class OptionError(Error):
  """Error for bad command line options."""


class FileMultiplexer(object):
  def __init__(self, fd1, fd2) :
    self.__fd1 = fd1
    self.__fd2 = fd2

  def __del__(self) :
    if self.__fd1 != sys.stdout and self.__fd1 != sys.stderr:
      self.__fd1.close()
    if self.__fd2 != sys.stdout and self.__fd2 != sys.stderr:
      self.__fd2.close()

  def write(self, text) :
    self.__fd1.write(text)
    self.__fd2.write(text)

  def flush(self) :
    self.__fd1.flush()
    self.__fd2.flush()


class ClientRestrictingServerMixIn:
  """Implements verify_request to limit connections to our configured IP
  address."""

  def verify_request(self, _request, client_address):
    return client_address[0] == self.server_address[0]


class BrokenPipeHandlerMixIn:
  """Allows the server to deal with "broken pipe" errors (which happen if the
  browser quits with outstanding requests, like for the favicon). This mix-in
  requires the class to derive from SocketServer.BaseServer and not override its
  handle_error() method. """

  def handle_error(self, request, client_address):
    value = sys.exc_info()[1]
    if isinstance(value, tlslite.errors.TLSClosedConnectionError):
      print "testserver.py: Closed connection"
      return
    if isinstance(value, socket.error):
      err = value.args[0]
      if sys.platform in ('win32', 'cygwin'):
        # "An established connection was aborted by the software in your host."
        pipe_err = 10053
      else:
        pipe_err = errno.EPIPE
      if err == pipe_err:
        print "testserver.py: Broken pipe"
        return
      if err == errno.ECONNRESET:
        print "testserver.py: Connection reset by peer"
        return
    SocketServer.BaseServer.handle_error(self, request, client_address)


class StoppableHTTPServer(BaseHTTPServer.HTTPServer):
  """This is a specialization of BaseHTTPServer to allow it
  to be exited cleanly (by setting its "stop" member to True)."""

  def serve_forever(self):
    self.stop = False
    self.nonce_time = None
    while not self.stop:
      self.handle_request()
    self.socket.close()


def MultiplexerHack(std_fd, log_fd):
  """Creates a FileMultiplexer that will write to both specified files.

  When running on Windows XP bots, stdout and stderr will be invalid file
  handles, so log_fd will be returned directly.  (This does not occur if you
  run the test suite directly from a console, but only if the output of the
  test executable is redirected.)
  """
  if std_fd.fileno() <= 0:
    return log_fd
  return FileMultiplexer(std_fd, log_fd)


class BasePageHandler(BaseHTTPServer.BaseHTTPRequestHandler):

  def __init__(self, request, client_address, socket_server,
               connect_handlers, get_handlers, head_handlers, post_handlers,
               put_handlers):
    self._connect_handlers = connect_handlers
    self._get_handlers = get_handlers
    self._head_handlers = head_handlers
    self._post_handlers = post_handlers
    self._put_handlers = put_handlers
    BaseHTTPServer.BaseHTTPRequestHandler.__init__(
      self, request, client_address, socket_server)

  def log_request(self, *args, **kwargs):
    # Disable request logging to declutter test log output.
    pass

  def _ShouldHandleRequest(self, handler_name):
    """Determines if the path can be handled by the handler.

    We consider a handler valid if the path begins with the
    handler name. It can optionally be followed by "?*", "/*".
    """

    pattern = re.compile('%s($|\?|/).*' % handler_name)
    return pattern.match(self.path)

  def do_CONNECT(self):
    for handler in self._connect_handlers:
      if handler():
        return

  def do_GET(self):
    for handler in self._get_handlers:
      if handler():
        return

  def do_HEAD(self):
    for handler in self._head_handlers:
      if handler():
        return

  def do_POST(self):
    for handler in self._post_handlers:
      if handler():
        return

  def do_PUT(self):
    for handler in self._put_handlers:
      if handler():
        return


class TestServerRunner(object):
  """Runs a test server and communicates with the controlling C++ test code.

  Subclasses should override the create_server method to create their server
  object, and the add_options method to add their own options.
  """

  def __init__(self):
    self.option_parser = optparse.OptionParser()
    self.add_options()

  def main(self):
    self.options, self.args = self.option_parser.parse_args()

    logfile = open(self.options.log_file, 'w')

    # http://crbug.com/248796 : Error logs streamed to normal sys.stderr will be
    # written to HTTP response payload when remote test server is used.
    # For this reason, some tests like ResourceFetcherTests.ResourceFetcher404
    # were failing on Android because remote test server is being used there.
    # To fix them, we need to use sys.stdout as sys.stderr if remote test server
    # is used.
    if self.options.on_remote_server:
      sys.stderr = sys.stdout

    sys.stderr = MultiplexerHack(sys.stderr, logfile)
    if self.options.log_to_console:
      sys.stdout = MultiplexerHack(sys.stdout, logfile)
    else:
      sys.stdout = logfile

    server_data = {
      'host': self.options.host,
    }
    self.server = self.create_server(server_data)
    self._notify_startup_complete(server_data)
    self.run_server()

  def create_server(self, server_data):
    """Creates a server object and returns it.

    Must populate server_data['port'], and can set additional server_data
    elements if desired."""
    raise NotImplementedError()

  def run_server(self):
    try:
      self.server.serve_forever()
    except KeyboardInterrupt:
      print 'shutting down server'
      self.server.stop = True

  def add_options(self):
    self.option_parser.add_option('--startup-pipe', type='int',
                                  dest='startup_pipe',
                                  help='File handle of pipe to parent process')
    self.option_parser.add_option('--log-to-console', action='store_const',
                                  const=True, default=False,
                                  dest='log_to_console',
                                  help='Enables or disables sys.stdout logging '
                                  'to the console.')
    self.option_parser.add_option('--log-file', default='testserver.log',
                                  dest='log_file',
                                  help='The name of the server log file.')
    self.option_parser.add_option('--port', default=0, type='int',
                                  help='Port used by the server. If '
                                  'unspecified, the server will listen on an '
                                  'ephemeral port.')
    self.option_parser.add_option('--host', default='127.0.0.1',
                                  dest='host',
                                  help='Hostname or IP upon which the server '
                                  'will listen. Client connections will also '
                                  'only be allowed from this address.')
    self.option_parser.add_option('--data-dir', dest='data_dir',
                                  help='Directory from which to read the '
                                  'files.')
    self.option_parser.add_option('--on-remote-server', action='store_const',
                                  const=True, default=False,
                                  dest='on_remote_server',
                                  help='Whether remote server is being used or '
                                  'not.')

  def _notify_startup_complete(self, server_data):
    # Notify the parent that we've started. (BaseServer subclasses
    # bind their sockets on construction.)
    if self.options.startup_pipe is not None:
      server_data_json = json.dumps(server_data)
      server_data_len = len(server_data_json)
      print 'sending server_data: %s (%d bytes)' % (
        server_data_json, server_data_len)
      if sys.platform == 'win32':
        fd = msvcrt.open_osfhandle(self.options.startup_pipe, 0)
      else:
        fd = self.options.startup_pipe
      startup_pipe = os.fdopen(fd, "w")
      # First write the data length as an unsigned 4-byte value.  This
      # is _not_ using network byte ordering since the other end of the
      # pipe is on the same machine.
      startup_pipe.write(struct.pack('=L', server_data_len))
      startup_pipe.write(server_data_json)
      startup_pipe.close()
