#
#

# Copyright (C) 2007, 2008, 2010, 2012 Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""HTTP server module.

"""

import BaseHTTPServer
import cgi
import logging
import os
import socket
import time
import signal
import asyncore

from ganeti import http
from ganeti import utils
from ganeti import netutils
from ganeti import compat
from ganeti import errors


WEEKDAYNAME = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
MONTHNAME = [None,
             "Jan", "Feb", "Mar", "Apr", "May", "Jun",
             "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]

# Default error message
DEFAULT_ERROR_CONTENT_TYPE = "text/html"
DEFAULT_ERROR_MESSAGE = """\
<html>
<head>
<title>Error response</title>
</head>
<body>
<h1>Error response</h1>
<p>Error code %(code)d.
<p>Message: %(message)s.
<p>Error code explanation: %(code)s = %(explain)s.
</body>
</html>
"""


def _DateTimeHeader(gmnow=None):
  """Return the current date and time formatted for a message header.

  The time MUST be in the GMT timezone.

  """
  if gmnow is None:
    gmnow = time.gmtime()
  (year, month, day, hh, mm, ss, wd, _, _) = gmnow
  return ("%s, %02d %3s %4d %02d:%02d:%02d GMT" %
          (WEEKDAYNAME[wd], day, MONTHNAME[month], year, hh, mm, ss))


class _HttpServerRequest(object):
  """Data structure for HTTP request on server side.

  """
  def __init__(self, method, path, headers, body, sock):
    # Request attributes
    self.request_method = method
    self.request_path = path
    self.request_headers = headers
    self.request_body = body
    self.request_sock = sock

    # Response attributes
    self.resp_headers = {}

    # Private data for request handler (useful in combination with
    # authentication)
    self.private = None

  def __repr__(self):
    status = ["%s.%s" % (self.__class__.__module__, self.__class__.__name__),
              self.request_method, self.request_path,
              "headers=%r" % str(self.request_headers),
              "body=%r" % (self.request_body, )]

    return "<%s at %#x>" % (" ".join(status), id(self))


class _HttpServerToClientMessageWriter(http.HttpMessageWriter):
  """Writes an HTTP response to client.

  """
  def __init__(self, sock, request_msg, response_msg, write_timeout):
    """Writes the response to the client.

    @type sock: socket
    @param sock: Target socket
    @type request_msg: http.HttpMessage
    @param request_msg: Request message, required to determine whether
        response may have a message body
    @type response_msg: http.HttpMessage
    @param response_msg: Response message
    @type write_timeout: float
    @param write_timeout: Write timeout for socket

    """
    self._request_msg = request_msg
    self._response_msg = response_msg
    http.HttpMessageWriter.__init__(self, sock, response_msg, write_timeout)

  def HasMessageBody(self):
    """Logic to detect whether response should contain a message body.

    """
    if self._request_msg.start_line:
      request_method = self._request_msg.start_line.method
    else:
      request_method = None

    response_code = self._response_msg.start_line.code

    # RFC2616, section 4.3: "A message-body MUST NOT be included in a request
    # if the specification of the request method (section 5.1.1) does not allow
    # sending an entity-body in requests"
    #
    # RFC2616, section 9.4: "The HEAD method is identical to GET except that
    # the server MUST NOT return a message-body in the response."
    #
    # RFC2616, section 10.2.5: "The 204 response MUST NOT include a
    # message-body [...]"
    #
    # RFC2616, section 10.3.5: "The 304 response MUST NOT contain a
    # message-body, [...]"

    return (http.HttpMessageWriter.HasMessageBody(self) and
            (request_method is not None and
             request_method != http.HTTP_HEAD) and
            response_code >= http.HTTP_OK and
            response_code not in (http.HTTP_NO_CONTENT,
                                  http.HTTP_NOT_MODIFIED))


class _HttpClientToServerMessageReader(http.HttpMessageReader):
  """Reads an HTTP request sent by client.

  """
  # Length limits
  START_LINE_LENGTH_MAX = 8192
  HEADER_LENGTH_MAX = 4096

  def ParseStartLine(self, start_line):
    """Parses the start line sent by client.

    Example: "GET /index.html HTTP/1.1"

    @type start_line: string
    @param start_line: Start line

    """
    # Empty lines are skipped when reading
    assert start_line

    logging.debug("HTTP request: %s", start_line)

    words = start_line.split()

    if len(words) == 3:
      [method, path, version] = words
      if version[:5] != "HTTP/":
        raise http.HttpBadRequest("Bad request version (%r)" % version)

      try:
        base_version_number = version.split("/", 1)[1]
        version_number = base_version_number.split(".")

        # RFC 2145 section 3.1 says there can be only one "." and
        #   - major and minor numbers MUST be treated as
        #      separate integers;
        #   - HTTP/2.4 is a lower version than HTTP/2.13, which in
        #      turn is lower than HTTP/12.3;
        #   - Leading zeros MUST be ignored by recipients.
        if len(version_number) != 2:
          raise http.HttpBadRequest("Bad request version (%r)" % version)

        version_number = (int(version_number[0]), int(version_number[1]))
      except (ValueError, IndexError):
        raise http.HttpBadRequest("Bad request version (%r)" % version)

      if version_number >= (2, 0):
        raise http.HttpVersionNotSupported("Invalid HTTP Version (%s)" %
                                           base_version_number)

    elif len(words) == 2:
      version = http.HTTP_0_9
      [method, path] = words
      if method != http.HTTP_GET:
        raise http.HttpBadRequest("Bad HTTP/0.9 request type (%r)" % method)

    else:
      raise http.HttpBadRequest("Bad request syntax (%r)" % start_line)

    return http.HttpClientToServerStartLine(method, path, version)


def _HandleServerRequestInner(handler, req_msg, reader):
  """Calls the handler function for the current request.

  """
  handler_context = _HttpServerRequest(req_msg.start_line.method,
                                       req_msg.start_line.path,
                                       req_msg.headers,
                                       req_msg.body,
                                       reader.sock)

  logging.debug("Handling request %r", handler_context)

  try:
    try:
      # Authentication, etc.
      handler.PreHandleRequest(handler_context)

      # Call actual request handler
      result = handler.HandleRequest(handler_context)
    except (http.HttpException, errors.RapiTestResult,
            KeyboardInterrupt, SystemExit):
      raise
    except Exception, err:
      logging.exception("Caught exception")
      raise http.HttpInternalServerError(message=str(err))
    except:
      logging.exception("Unknown exception")
      raise http.HttpInternalServerError(message="Unknown error")

    if not isinstance(result, basestring):
      raise http.HttpError("Handler function didn't return string type")

    return (http.HTTP_OK, handler_context.resp_headers, result)
  finally:
    # No reason to keep this any longer, even for exceptions
    handler_context.private = None


class HttpResponder(object):
  # The default request version.  This only affects responses up until
  # the point where the request line is parsed, so it mainly decides what
  # the client gets back when sending a malformed request line.
  # Most web servers default to HTTP 0.9, i.e. don't send a status line.
  default_request_version = http.HTTP_0_9

  responses = BaseHTTPServer.BaseHTTPRequestHandler.responses

  def __init__(self, handler):
    """Initializes this class.

    """
    self._handler = handler

  def __call__(self, fn):
    """Handles a request.

    @type fn: callable
    @param fn: Callback for retrieving HTTP request, must return a tuple
      containing request message (L{http.HttpMessage}) and C{None} or the
      message reader (L{_HttpClientToServerMessageReader})

    """
    response_msg = http.HttpMessage()
    response_msg.start_line = \
      http.HttpServerToClientStartLine(version=self.default_request_version,
                                       code=None, reason=None)

    force_close = True

    try:
      (request_msg, req_msg_reader) = fn()

      response_msg.start_line.version = request_msg.start_line.version

      # RFC2616, 14.23: All Internet-based HTTP/1.1 servers MUST respond
      # with a 400 (Bad Request) status code to any HTTP/1.1 request
      # message which lacks a Host header field.
      if (request_msg.start_line.version == http.HTTP_1_1 and
          not (request_msg.headers and
               http.HTTP_HOST in request_msg.headers)):
        raise http.HttpBadRequest(message="Missing Host header")

      (response_msg.start_line.code, response_msg.headers,
       response_msg.body) = \
        _HandleServerRequestInner(self._handler, request_msg, req_msg_reader)
    except http.HttpException, err:
      self._SetError(self.responses, self._handler, response_msg, err)
    else:
      # Only wait for client to close if we didn't have any exception.
      force_close = False

    return (request_msg, req_msg_reader, force_close,
            self._Finalize(self.responses, response_msg))

  @staticmethod
  def _SetError(responses, handler, response_msg, err):
    """Sets the response code and body from a HttpException.

    @type err: HttpException
    @param err: Exception instance

    """
    try:
      (shortmsg, longmsg) = responses[err.code]
    except KeyError:
      shortmsg = longmsg = "Unknown"

    if err.message:
      message = err.message
    else:
      message = shortmsg

    values = {
      "code": err.code,
      "message": cgi.escape(message),
      "explain": longmsg,
      }

    (content_type, body) = handler.FormatErrorMessage(values)

    headers = {
      http.HTTP_CONTENT_TYPE: content_type,
      }

    if err.headers:
      headers.update(err.headers)

    response_msg.start_line.code = err.code
    response_msg.headers = headers
    response_msg.body = body

  @staticmethod
  def _Finalize(responses, msg):
    assert msg.start_line.reason is None

    if not msg.headers:
      msg.headers = {}

    msg.headers.update({
      # TODO: Keep-alive is not supported
      http.HTTP_CONNECTION: "close",
      http.HTTP_DATE: _DateTimeHeader(),
      http.HTTP_SERVER: http.HTTP_GANETI_VERSION,
      })

    # Get response reason based on code
    try:
      code_desc = responses[msg.start_line.code]
    except KeyError:
      reason = ""
    else:
      (reason, _) = code_desc

    msg.start_line.reason = reason

    return msg


class HttpServerRequestExecutor(object):
  """Implements server side of HTTP.

  This class implements the server side of HTTP. It's based on code of
  Python's BaseHTTPServer, from both version 2.4 and 3k. It does not
  support non-ASCII character encodings. Keep-alive connections are
  not supported.

  """
  # Timeouts in seconds for socket layer
  WRITE_TIMEOUT = 10
  READ_TIMEOUT = 10
  CLOSE_TIMEOUT = 1

  def __init__(self, server, handler, sock, client_addr):
    """Initializes this class.

    """
    responder = HttpResponder(handler)

    # Disable Python's timeout
    sock.settimeout(None)

    # Operate in non-blocking mode
    sock.setblocking(0)

    request_msg_reader = None
    force_close = True

    logging.debug("Connection from %s:%s", client_addr[0], client_addr[1])
    try:
      # Block for closing connection
      try:
        # Do the secret SSL handshake
        if server.using_ssl:
          sock.set_accept_state()
          try:
            http.Handshake(sock, self.WRITE_TIMEOUT)
          except http.HttpSessionHandshakeUnexpectedEOF:
            logging.debug("Unexpected EOF from %s:%s" % (client_addr[0], client_addr[1]))
            # Ignore rest
            return

        (request_msg, request_msg_reader, force_close, response_msg) = \
          responder(compat.partial(self._ReadRequest, sock, self.READ_TIMEOUT))
        if response_msg:
          # HttpMessage.start_line can be of different types
          # Instance of 'HttpClientToServerStartLine' has no 'code' member
          # pylint: disable=E1103,E1101
          logging.info("%s:%s %s %s", client_addr[0], client_addr[1],
                       request_msg.start_line, response_msg.start_line.code)
          self._SendResponse(sock, request_msg, response_msg,
                             self.WRITE_TIMEOUT)
      finally:
        http.ShutdownConnection(sock, self.CLOSE_TIMEOUT, self.WRITE_TIMEOUT,
                                request_msg_reader, force_close)

      sock.close()
    finally:
      logging.debug("Disconnected %s:%s", client_addr[0], client_addr[1])

  @staticmethod
  def _ReadRequest(sock, timeout):
    """Reads a request sent by client.

    """
    msg = http.HttpMessage()

    try:
      reader = _HttpClientToServerMessageReader(sock, msg, timeout)
    except http.HttpSocketTimeout:
      raise http.HttpError("Timeout while reading request")
    except socket.error, err:
      raise http.HttpError("Error reading request: %s" % err)

    return (msg, reader)

  @staticmethod
  def _SendResponse(sock, req_msg, msg, timeout):
    """Sends the response to the client.

    """
    try:
      _HttpServerToClientMessageWriter(sock, req_msg, msg, timeout)
    except http.HttpSocketTimeout:
      raise http.HttpError("Timeout while sending response")
    except socket.error, err:
      raise http.HttpError("Error sending response: %s" % err)


class HttpServer(http.HttpBase, asyncore.dispatcher):
  """Generic HTTP server class

  """
  MAX_CHILDREN = 20

  def __init__(self, mainloop, local_address, port, handler,
               ssl_params=None, ssl_verify_peer=False,
               request_executor_class=None, ssl_verify_callback=None):
    """Initializes the HTTP server

    @type mainloop: ganeti.daemon.Mainloop
    @param mainloop: Mainloop used to poll for I/O events
    @type local_address: string
    @param local_address: Local IP address to bind to
    @type port: int
    @param port: TCP port to listen on
    @type ssl_params: HttpSslParams
    @param ssl_params: SSL key and certificate
    @type ssl_verify_peer: bool
    @param ssl_verify_peer: Whether to require client certificate
        and compare it with our certificate
    @type request_executor_class: class
    @param request_executor_class: a class derived from the
        HttpServerRequestExecutor class

    """
    http.HttpBase.__init__(self)
    asyncore.dispatcher.__init__(self)

    if request_executor_class is None:
      self.request_executor = HttpServerRequestExecutor
    else:
      self.request_executor = request_executor_class

    self.mainloop = mainloop
    self.local_address = local_address
    self.port = port
    self.handler = handler
    family = netutils.IPAddress.GetAddressFamily(local_address)
    self.socket = self._CreateSocket(ssl_params, ssl_verify_peer, family,
                                     ssl_verify_callback)

    # Allow port to be reused
    self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

    self._children = []
    self.set_socket(self.socket)
    self.accepting = True
    mainloop.RegisterSignal(self)

  def Start(self):
    self.socket.bind((self.local_address, self.port))
    self.socket.listen(1024)

  def Stop(self):
    self.socket.close()

  def handle_accept(self):
    self._IncomingConnection()

  def OnSignal(self, signum):
    if signum == signal.SIGCHLD:
      self._CollectChildren(True)

  def _CollectChildren(self, quick):
    """Checks whether any child processes are done

    @type quick: bool
    @param quick: Whether to only use non-blocking functions

    """
    if not quick:
      # Don't wait for other processes if it should be a quick check
      while len(self._children) > self.MAX_CHILDREN:
        try:
          # Waiting without a timeout brings us into a potential DoS situation.
          # As soon as too many children run, we'll not respond to new
          # requests. The real solution would be to add a timeout for children
          # and killing them after some time.
          pid, _ = os.waitpid(0, 0)
        except os.error:
          pid = None
        if pid and pid in self._children:
          self._children.remove(pid)

    for child in self._children:
      try:
        pid, _ = os.waitpid(child, os.WNOHANG)
      except os.error:
        pid = None
      if pid and pid in self._children:
        self._children.remove(pid)

  def _IncomingConnection(self):
    """Called for each incoming connection

    """
    # pylint: disable=W0212
    t_start = time.time()
    (connection, client_addr) = self.socket.accept()

    self._CollectChildren(False)

    try:
      pid = os.fork()
    except OSError:
      logging.exception("Failed to fork on request from %s:%s",
                        client_addr[0], client_addr[1])
      # Immediately close the connection. No SSL handshake has been done.
      try:
        connection.close()
      except socket.error:
        pass
      return

    if pid == 0:
      # Child process
      try:
        # The client shouldn't keep the listening socket open. If the parent
        # process is restarted, it would fail when there's already something
        # listening (in this case its own child from a previous run) on the
        # same port.
        try:
          self.socket.close()
        except socket.error:
          pass
        self.socket = None

        # In case the handler code uses temporary files
        utils.ResetTempfileModule()

        t_setup = time.time()
        self.request_executor(self, self.handler, connection, client_addr)
        t_end = time.time()
        logging.debug("Request from %s:%s executed in: %.4f [setup: %.4f] [workers: %d]" % (
            client_addr[0], client_addr[1], t_end - t_start, t_setup - t_start, len(self._children)))

      except Exception: # pylint: disable=W0703
        logging.exception("Error while handling request from %s:%s",
                          client_addr[0], client_addr[1])
        os._exit(1)
      os._exit(0)
    else:
      self._children.append(pid)


class HttpServerHandler(object):
  """Base class for handling HTTP server requests.

  Users of this class must subclass it and override the L{HandleRequest}
  function.

  """
  def PreHandleRequest(self, req):
    """Called before handling a request.

    Can be overridden by a subclass.

    """

  def HandleRequest(self, req):
    """Handles a request.

    Must be overridden by subclass.

    """
    raise NotImplementedError()

  @staticmethod
  def FormatErrorMessage(values):
    """Formats the body of an error message.

    @type values: dict
    @param values: dictionary with keys C{code}, C{message} and C{explain}.
    @rtype: tuple; (string, string)
    @return: Content-type and response body

    """
    return (DEFAULT_ERROR_CONTENT_TYPE, DEFAULT_ERROR_MESSAGE % values)
