| // 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/nacl_subprocess.h" |
| |
| #include <stdarg.h> |
| |
| #include <sstream> |
| |
| #include "components/nacl/renderer/plugin/plugin_error.h" |
| #include "components/nacl/renderer/plugin/srpc_params.h" |
| #include "native_client/src/shared/srpc/nacl_srpc.h" |
| |
| namespace plugin { |
| |
| NaClSubprocess::NaClSubprocess(const std::string& description, |
| ServiceRuntime* service_runtime, |
| SrpcClient* srpc_client) |
| : description_(description), |
| service_runtime_(service_runtime), |
| srpc_client_(srpc_client) { |
| } |
| |
| std::string NaClSubprocess::detailed_description() const { |
| std::stringstream ss; |
| ss << description() |
| << "={ this=" << static_cast<const void*>(this) |
| << ", srpc_client=" << static_cast<void*>(srpc_client_.get()) |
| << ", service_runtime=" << static_cast<void*>(service_runtime_.get()) |
| << " }"; |
| return ss.str(); |
| } |
| |
| // Shutdown the socket connection and service runtime, in that order. |
| void NaClSubprocess::Shutdown() { |
| srpc_client_.reset(NULL); |
| if (service_runtime_.get() != NULL) { |
| service_runtime_->Shutdown(); |
| service_runtime_.reset(NULL); |
| } |
| } |
| |
| NaClSubprocess::~NaClSubprocess() { |
| Shutdown(); |
| } |
| |
| bool NaClSubprocess::StartSrpcServices() { |
| srpc_client_.reset(service_runtime_->SetupAppChannel()); |
| return NULL != srpc_client_.get(); |
| } |
| |
| bool NaClSubprocess::InvokeSrpcMethod(const std::string& method_name, |
| const std::string& input_signature, |
| SrpcParams* params, |
| ...) { |
| va_list vl; |
| va_start(vl, params); |
| bool result = VInvokeSrpcMethod(method_name, input_signature, params, vl); |
| va_end(vl); |
| return result; |
| } |
| |
| bool NaClSubprocess::VInvokeSrpcMethod(const std::string& method_name, |
| const std::string& input_signature, |
| SrpcParams* params, |
| va_list vl) { |
| if (NULL == srpc_client_.get()) { |
| PLUGIN_PRINTF(("VInvokeSrpcMethod (no srpc_client_)\n")); |
| return false; |
| } |
| if (!srpc_client_->HasMethod(method_name)) { |
| PLUGIN_PRINTF(("VInvokeSrpcMethod (no %s method found)\n", |
| method_name.c_str())); |
| return false; |
| } |
| if (!srpc_client_->InitParams(method_name, params)) { |
| PLUGIN_PRINTF(("VInvokeSrpcMethod (InitParams failed)\n")); |
| return false; |
| } |
| // Marshall inputs. |
| for (size_t i = 0; i < input_signature.length(); ++i) { |
| char c = input_signature[i]; |
| // Only handle the limited number of SRPC types used for PNaCl. |
| // Add more as needed. |
| switch (c) { |
| default: |
| PLUGIN_PRINTF(("PnaclSrpcLib::InvokeSrpcMethod unhandled type: %c\n", |
| c)); |
| return false; |
| case NACL_SRPC_ARG_TYPE_BOOL: { |
| int input = va_arg(vl, int); |
| params->ins()[i]->u.bval = input; |
| break; |
| } |
| case NACL_SRPC_ARG_TYPE_DOUBLE: { |
| double input = va_arg(vl, double); |
| params->ins()[i]->u.dval = input; |
| break; |
| } |
| case NACL_SRPC_ARG_TYPE_CHAR_ARRAY: { |
| // SrpcParam's destructor *should* free the allocated array |
| const char* orig_arr = va_arg(vl, const char*); |
| size_t len = va_arg(vl, size_t); |
| char* input = (char *)malloc(len); |
| if (!input) { |
| PLUGIN_PRINTF(("VInvokeSrpcMethod (allocation failure)\n")); |
| return false; |
| } |
| memcpy(input, orig_arr, len); |
| params->ins()[i]->arrays.carr = input; |
| params->ins()[i]->u.count = static_cast<nacl_abi_size_t>(len); |
| break; |
| } |
| case NACL_SRPC_ARG_TYPE_HANDLE: { |
| NaClSrpcImcDescType input = va_arg(vl, NaClSrpcImcDescType); |
| params->ins()[i]->u.hval = input; |
| break; |
| } |
| case NACL_SRPC_ARG_TYPE_INT: { |
| int32_t input = va_arg(vl, int32_t); |
| params->ins()[i]->u.ival = input; |
| break; |
| } |
| case NACL_SRPC_ARG_TYPE_LONG: { |
| int64_t input = va_arg(vl, int64_t); |
| params->ins()[i]->u.lval = input; |
| break; |
| } |
| case NACL_SRPC_ARG_TYPE_STRING: { |
| // SrpcParam's destructor *should* free the dup'ed string. |
| const char* orig_str = va_arg(vl, const char*); |
| char* input = strdup(orig_str); |
| if (!input) { |
| PLUGIN_PRINTF(("VInvokeSrpcMethod (allocation failure)\n")); |
| return false; |
| } |
| params->ins()[i]->arrays.str = input; |
| break; |
| } |
| } |
| } |
| return srpc_client_->Invoke(method_name, params); |
| } |
| |
| } // namespace plugin |