/*
 * 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.
 */

#include "components/nacl/renderer/plugin/srpc_client.h"

#include <string.h>

#include "components/nacl/renderer/plugin/plugin.h"
#include "components/nacl/renderer/plugin/srpc_params.h"
#include "components/nacl/renderer/plugin/utility.h"
#include "native_client/src/shared/platform/nacl_log.h"

namespace plugin {

typedef bool (*RpcFunction)(void* obj, SrpcParams* params);

// MethodInfo records the method names and type signatures of an SRPC server.
class MethodInfo {
 public:
  // statically defined method - called through a pointer
  MethodInfo(const RpcFunction function_ptr,
             const char* name,
             const char* ins,
             const char* outs,
             // index is set to UINT_MAX for methods implemented by the plugin,
             // All methods implemented by nacl modules have indexes
             // that are lower than UINT_MAX.
             const uint32_t index = UINT_MAX) :
    function_ptr_(function_ptr),
    name_(STRDUP(name)),
    ins_(STRDUP(ins)),
    outs_(STRDUP(outs)),
    index_(index) { }

  ~MethodInfo() {
    free(reinterpret_cast<void*>(name_));
    free(reinterpret_cast<void*>(ins_));
    free(reinterpret_cast<void*>(outs_));
  }

  RpcFunction function_ptr() const { return function_ptr_; }
  char* name() const { return name_; }
  char* ins() const { return ins_; }
  char* outs() const { return outs_; }
  uint32_t index() const { return index_; }

 private:
  NACL_DISALLOW_COPY_AND_ASSIGN(MethodInfo);
  RpcFunction function_ptr_;
  char* name_;
  char* ins_;
  char* outs_;
  uint32_t index_;
};

SrpcClient::SrpcClient()
    : srpc_channel_initialised_(false) {
  PLUGIN_PRINTF(("SrpcClient::SrpcClient (this=%p)\n",
                 static_cast<void*>(this)));
  NaClSrpcChannelInitialize(&srpc_channel_);
}

SrpcClient* SrpcClient::New(nacl::DescWrapper* wrapper) {
  nacl::scoped_ptr<SrpcClient> srpc_client(new SrpcClient());
  if (!srpc_client->Init(wrapper)) {
    PLUGIN_PRINTF(("SrpcClient::New (SrpcClient::Init failed)\n"));
    return NULL;
  }
  return srpc_client.release();
}

bool SrpcClient::Init(nacl::DescWrapper* wrapper) {
  PLUGIN_PRINTF(("SrpcClient::Init (this=%p, wrapper=%p)\n",
                 static_cast<void*>(this),
                 static_cast<void*>(wrapper)));
  // Open the channel to pass RPC information back and forth
  if (!NaClSrpcClientCtor(&srpc_channel_, wrapper->desc())) {
    return false;
  }
  srpc_channel_initialised_ = true;
  PLUGIN_PRINTF(("SrpcClient::Init (Ctor worked)\n"));
  // Record the method names in a convenient way for later dispatches.
  GetMethods();
  PLUGIN_PRINTF(("SrpcClient::Init (GetMethods worked)\n"));
  return true;
}

SrpcClient::~SrpcClient() {
  PLUGIN_PRINTF(("SrpcClient::~SrpcClient (this=%p, has_srpc_channel=%d)\n",
                 static_cast<void*>(this), srpc_channel_initialised_));
  // And delete the connection.
  if (srpc_channel_initialised_) {
    PLUGIN_PRINTF(("SrpcClient::~SrpcClient (destroying srpc_channel)\n"));
    NaClSrpcDtor(&srpc_channel_);
  }
  for (Methods::iterator iter = methods_.begin();
       iter != methods_.end();
       ++iter) {
    delete iter->second;
  }
  PLUGIN_PRINTF(("SrpcClient::~SrpcClient (return)\n"));
}

void SrpcClient::GetMethods() {
  PLUGIN_PRINTF(("SrpcClient::GetMethods (this=%p)\n",
                 static_cast<void*>(this)));
  if (NULL == srpc_channel_.client) {
    return;
  }
  uint32_t method_count = NaClSrpcServiceMethodCount(srpc_channel_.client);
  // Intern the methods into a mapping from identifiers to MethodInfo.
  for (uint32_t i = 0; i < method_count; ++i) {
    int retval;
    const char* method_name;
    const char* input_types;
    const char* output_types;

    retval = NaClSrpcServiceMethodNameAndTypes(srpc_channel_.client,
                                               i,
                                               &method_name,
                                               &input_types,
                                               &output_types);
    if (!retval) {
      return;
    }
    if (!IsValidIdentifierString(method_name, NULL)) {
      // If name is not an ECMAScript identifier, do not enter it into the
      // methods_ table.
      continue;
    }
    MethodInfo* method_info =
        new MethodInfo(NULL, method_name, input_types, output_types, i);
    if (NULL == method_info) {
      return;
    }
    // Install in the map only if successfully read.
    methods_[method_name] = method_info;
  }
}

bool SrpcClient::HasMethod(const std::string& method_name) {
  bool has_method = (NULL != methods_[method_name]);
  PLUGIN_PRINTF((
      "SrpcClient::HasMethod (this=%p, method_name='%s', return %d)\n",
      static_cast<void*>(this), method_name.c_str(), has_method));
  return has_method;
}

bool SrpcClient::InitParams(const std::string& method_name,
                            SrpcParams* params) {
  MethodInfo* method_info = methods_[method_name];
  if (method_info) {
    return params->Init(method_info->ins(), method_info->outs());
  }
  return false;
}

bool SrpcClient::Invoke(const std::string& method_name, SrpcParams* params) {
  // It would be better if we could set the exception on each detailed failure
  // case.  However, there are calls to Invoke from within the plugin itself,
  // and these could leave residual exceptions pending.  This seems to be
  // happening specifically with hard_shutdowns.
  PLUGIN_PRINTF(("SrpcClient::Invoke (this=%p, method_name='%s', params=%p)\n",
                 static_cast<void*>(this),
                 method_name.c_str(),
                 static_cast<void*>(params)));

  // Ensure Invoke was called with a method name that has a binding.
  if (NULL == methods_[method_name]) {
    PLUGIN_PRINTF(("SrpcClient::Invoke (ident not in methods_)\n"));
    return false;
  }

  PLUGIN_PRINTF(("SrpcClient::Invoke (sending the rpc)\n"));
  // Call the method
  last_error_ = NaClSrpcInvokeV(&srpc_channel_,
                                methods_[method_name]->index(),
                                params->ins(),
                                params->outs());
  PLUGIN_PRINTF(("SrpcClient::Invoke (response=%d)\n", last_error_));
  if (NACL_SRPC_RESULT_OK != last_error_) {
    PLUGIN_PRINTF(("SrpcClient::Invoke (err='%s', return 0)\n",
                   NaClSrpcErrorString(last_error_)));
    return false;
  }

  PLUGIN_PRINTF(("SrpcClient::Invoke (return 1)\n"));
  return true;
}

void SrpcClient::AttachService(NaClSrpcService* service, void* instance_data) {
  srpc_channel_.server = service;
  srpc_channel_.server_instance_data = instance_data;
}

}  // namespace plugin
