15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/plugin/nacl_subprocess.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdarg.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "native_client/src/shared/srpc/nacl_srpc.h"
10ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/plugin/plugin_error.h"
11ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/plugin/srpc_params.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace plugin {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)nacl::string NaClSubprocess::detailed_description() const {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nacl::stringstream ss;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ss << description()
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     << "={ this=" << static_cast<const void*>(this)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     << ", srpc_client=" << static_cast<void*>(srpc_client_.get())
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     << ", service_runtime=" << static_cast<void*>(service_runtime_.get())
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     << " }";
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ss.str();
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Shutdown the socket connection and service runtime, in that order.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NaClSubprocess::Shutdown() {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  srpc_client_.reset(NULL);
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service_runtime_.get() != NULL) {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_runtime_->Shutdown();
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_runtime_.reset(NULL);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NaClSubprocess::~NaClSubprocess() {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Shutdown();
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NaClSubprocess::StartSrpcServices() {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  srpc_client_.reset(service_runtime_->SetupAppChannel());
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL != srpc_client_.get();
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NaClSubprocess::InvokeSrpcMethod(const nacl::string& method_name,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const nacl::string& input_signature,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      SrpcParams* params,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      ...) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_list vl;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_start(vl, params);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool result = VInvokeSrpcMethod(method_name, input_signature, params, vl);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_end(vl);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NaClSubprocess::VInvokeSrpcMethod(const nacl::string& method_name,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const nacl::string& input_signature,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       SrpcParams* params,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       va_list vl) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == srpc_client_.get()) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PLUGIN_PRINTF(("VInvokeSrpcMethod (no srpc_client_)\n"));
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!srpc_client_->HasMethod(method_name)) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PLUGIN_PRINTF(("VInvokeSrpcMethod (no %s method found)\n",
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   method_name.c_str()));
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!srpc_client_->InitParams(method_name, params)) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PLUGIN_PRINTF(("VInvokeSrpcMethod (InitParams failed)\n"));
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Marshall inputs.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < input_signature.length(); ++i) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char c = input_signature[i];
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Only handle the limited number of SRPC types used for PNaCl.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Add more as needed.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (c) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PLUGIN_PRINTF(("PnaclSrpcLib::InvokeSrpcMethod unhandled type: %c\n",
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       c));
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case NACL_SRPC_ARG_TYPE_BOOL: {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int input = va_arg(vl, int);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        params->ins()[i]->u.bval = input;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case NACL_SRPC_ARG_TYPE_DOUBLE: {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        double input = va_arg(vl, double);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        params->ins()[i]->u.dval = input;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case NACL_SRPC_ARG_TYPE_CHAR_ARRAY: {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // SrpcParam's destructor *should* free the allocated array
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const char* orig_arr = va_arg(vl, const char*);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        size_t len = va_arg(vl, size_t);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        char* input = (char *)malloc(len);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!input) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          PLUGIN_PRINTF(("VInvokeSrpcMethod (allocation failure)\n"));
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memcpy(input, orig_arr, len);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        params->ins()[i]->arrays.carr = input;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        params->ins()[i]->u.count = static_cast<nacl_abi_size_t>(len);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case NACL_SRPC_ARG_TYPE_HANDLE: {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NaClSrpcImcDescType input = va_arg(vl, NaClSrpcImcDescType);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        params->ins()[i]->u.hval = input;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case NACL_SRPC_ARG_TYPE_INT: {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int32_t input = va_arg(vl, int32_t);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        params->ins()[i]->u.ival = input;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case NACL_SRPC_ARG_TYPE_LONG: {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int64_t input = va_arg(vl, int64_t);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        params->ins()[i]->u.lval = input;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case NACL_SRPC_ARG_TYPE_STRING: {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // SrpcParam's destructor *should* free the dup'ed string.
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const char* orig_str = va_arg(vl, const char*);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        char* input = strdup(orig_str);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!input) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          PLUGIN_PRINTF(("VInvokeSrpcMethod (allocation failure)\n"));
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        params->ins()[i]->arrays.str = input;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return srpc_client_->Invoke(method_name, params);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace plugin
137