# Copyright 2014 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Module to implement the SimpleXMLRPCServer module using JSON-RPC.

This module uses SimpleXMLRPCServer as the base and only overrides those
portions that implement the XML-RPC protocol. These portions are rewritten
to use the JSON-RPC protocol instead.

When large portions of code need to be rewritten the original code and
comments are preserved. The intention here is to keep the amount of code
change to a minimum.

This module only depends on default Python modules, as well as jsonrpclib
which also uses only default modules. No third party code is required to
use this module.
"""
import fcntl
import json
import SimpleXMLRPCServer as _base
import SocketServer
import sys
import traceback
import jsonrpclib
try:
  import gzip
except ImportError:
  gzip = None #python can be built without zlib/gzip support


class SimpleJSONRPCRequestHandler(_base.SimpleXMLRPCRequestHandler):
  """Request handler class for received requests.

  This class extends the functionality of SimpleXMLRPCRequestHandler and only
  overrides the operations needed to change the protocol from XML-RPC to
  JSON-RPC.
  """

  def do_POST(self):
    """Handles the HTTP POST request.

    Attempts to interpret all HTTP POST requests as JSON-RPC calls,
    which are forwarded to the server's _dispatch method for handling.
    """
    # Check that the path is legal
    if not self.is_rpc_path_valid():
      self.report_404()
      return

    try:
      # Get arguments by reading body of request.
      # We read this in chunks to avoid straining
      # socket.read(); around the 10 or 15Mb mark, some platforms
      # begin to have problems (bug #792570).
      max_chunk_size = 10*1024*1024
      size_remaining = int(self.headers['content-length'])
      data = []
      while size_remaining:
        chunk_size = min(size_remaining, max_chunk_size)
        chunk = self.rfile.read(chunk_size)
        if not chunk:
          break
        data.append(chunk)
        size_remaining -= len(data[-1])
      data = ''.join(data)
      data = self.decode_request_content(data)

      if data is None:
        return  # response has been sent

      # In previous versions of SimpleXMLRPCServer, _dispatch
      # could be overridden in this class, instead of in
      # SimpleXMLRPCDispatcher. To maintain backwards compatibility,
      # check to see if a subclass implements _dispatch and dispatch
      # using that method if present.
      response = self.server._marshaled_dispatch(
          data, getattr(self, '_dispatch', None), self.path)

    except Exception, e: # This should only happen if the module is buggy
      # internal error, report as HTTP server error
      self.send_response(500)
      # Send information about the exception if requested
      if (hasattr(self.server, '_send_traceback_header') and
          self.server._send_traceback_header):
        self.send_header('X-exception', str(e))
        self.send_header('X-traceback', traceback.format_exc())

      self.send_header('Content-length', '0')
      self.end_headers()
    else:
      # got a valid JSON RPC response
      self.send_response(200)
      self.send_header('Content-type', 'application/json')

      if self.encode_threshold is not None:
        if len(response) > self.encode_threshold:
          q = self.accept_encodings().get('gzip', 0)
          if q:
            try:
              response = jsonrpclib.gzip_encode(response)
              self.send_header('Content-Encoding', 'gzip')
            except NotImplementedError:
              pass

      self.send_header('Content-length', str(len(response)))
      self.end_headers()
      self.wfile.write(response)


class SimpleJSONRPCDispatcher(_base.SimpleXMLRPCDispatcher):
  """Dispatcher for received JSON-RPC requests.

  This class extends the functionality of SimpleXMLRPCDispatcher and only
  overrides the operations needed to change the protocol from XML-RPC to
  JSON-RPC.
  """

  def _marshaled_dispatch(self, data, dispatch_method=None, path=None):
    """Dispatches an JSON-RPC method from marshalled (JSON) data.

    JSON-RPC methods are dispatched from the marshalled (JSON) data
    using the _dispatch method and the result is returned as
    marshalled data. For backwards compatibility, a dispatch
    function can be provided as an argument (see comment in
    SimpleJSONRPCRequestHandler.do_POST) but overriding the
    existing method through subclassing is the preferred means
    of changing method dispatch behavior.

    Returns:
      The JSON-RPC string to return.
    """
    method = ''
    params = []
    ident = ''
    try:
      request = json.loads(data)
      print 'request:', request
      jsonrpclib.ValidateRequest(request)
      method = request['method']
      params = request['params']
      ident = request['id']

      # generate response
      if dispatch_method is not None:
        response = dispatch_method(method, params)
      else:
        response = self._dispatch(method, params)
      response = jsonrpclib.CreateResponseString(response, ident)

    except jsonrpclib.Fault as fault:
      response = jsonrpclib.CreateResponseString(fault, ident)

    except:
      # report exception back to server
      exc_type, exc_value, _ = sys.exc_info()
      response = jsonrpclib.CreateResponseString(
          jsonrpclib.Fault(1, '%s:%s' % (exc_type, exc_value)), ident)
    print 'response:', response
    return response


class SimpleJSONRPCServer(SocketServer.TCPServer,
                          SimpleJSONRPCDispatcher):
  """Simple JSON-RPC server.

  This class mimics the functionality of SimpleXMLRPCServer and only
  overrides the operations needed to change the protocol from XML-RPC to
  JSON-RPC.
  """

  allow_reuse_address = True

  # Warning: this is for debugging purposes only! Never set this to True in
  # production code, as will be sending out sensitive information (exception
  # and stack trace details) when exceptions are raised inside
  # SimpleJSONRPCRequestHandler.do_POST
  _send_traceback_header = False

  def __init__(self, addr, requestHandler=SimpleJSONRPCRequestHandler,
               logRequests=True, allow_none=False, encoding=None,
               bind_and_activate=True):
    self.logRequests = logRequests
    SimpleJSONRPCDispatcher.__init__(self, allow_none, encoding)
    SocketServer.TCPServer.__init__(self, addr, requestHandler,
                                    bind_and_activate)

    # [Bug #1222790] If possible, set close-on-exec flag; if a
    # method spawns a subprocess, the subprocess shouldn't have
    # the listening socket open.
    if fcntl is not None and hasattr(fcntl, 'FD_CLOEXEC'):
      flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD)
      flags |= fcntl.FD_CLOEXEC
      fcntl.fcntl(self.fileno(), fcntl.F_SETFD, flags)
