srpc_client.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (c) 2012 The Chromium Authors. All rights reserved. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * found in the LICENSE file. 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/plugin/srpc_client.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "native_client/src/shared/platform/nacl_log.h" 12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/plugin/plugin.h" 13ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/plugin/srpc_params.h" 14ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/plugin/utility.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace plugin { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef bool (*RpcFunction)(void* obj, SrpcParams* params); 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MethodInfo records the method names and type signatures of an SRPC server. 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MethodInfo { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // statically defined method - called through a pointer 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MethodInfo(const RpcFunction function_ptr, 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* name, 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* ins, 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* outs, 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // index is set to UINT_MAX for methods implemented by the plugin, 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // All methods implemented by nacl modules have indexes 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that are lower than UINT_MAX. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint32_t index = UINT_MAX) : 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function_ptr_(function_ptr), 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name_(STRDUP(name)), 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ins_(STRDUP(ins)), 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) outs_(STRDUP(outs)), 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index_(index) { } 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~MethodInfo() { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(reinterpret_cast<void*>(name_)); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(reinterpret_cast<void*>(ins_)); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(reinterpret_cast<void*>(outs_)); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RpcFunction function_ptr() const { return function_ptr_; } 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* name() const { return name_; } 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* ins() const { return ins_; } 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* outs() const { return outs_; } 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t index() const { return index_; } 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NACL_DISALLOW_COPY_AND_ASSIGN(MethodInfo); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RpcFunction function_ptr_; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* name_; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* ins_; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* outs_; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t index_; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SrpcClient::SrpcClient() 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : srpc_channel_initialised_(false) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("SrpcClient::SrpcClient (this=%p)\n", 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<void*>(this))); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClSrpcChannelInitialize(&srpc_channel_); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SrpcClient* SrpcClient::New(nacl::DescWrapper* wrapper) { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::scoped_ptr<SrpcClient> srpc_client(new SrpcClient()); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!srpc_client->Init(wrapper)) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("SrpcClient::New (SrpcClient::Init failed)\n")); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return srpc_client.release(); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SrpcClient::Init(nacl::DescWrapper* wrapper) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("SrpcClient::Init (this=%p, wrapper=%p)\n", 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<void*>(this), 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<void*>(wrapper))); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Open the channel to pass RPC information back and forth 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!NaClSrpcClientCtor(&srpc_channel_, wrapper->desc())) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) srpc_channel_initialised_ = true; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("SrpcClient::Init (Ctor worked)\n")); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record the method names in a convenient way for later dispatches. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetMethods(); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("SrpcClient::Init (GetMethods worked)\n")); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SrpcClient::~SrpcClient() { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("SrpcClient::~SrpcClient (this=%p, has_srpc_channel=%d)\n", 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<void*>(this), srpc_channel_initialised_)); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // And delete the connection. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (srpc_channel_initialised_) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("SrpcClient::~SrpcClient (destroying srpc_channel)\n")); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClSrpcDtor(&srpc_channel_); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Methods::iterator iter = methods_.begin(); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != methods_.end(); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++iter) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete iter->second; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("SrpcClient::~SrpcClient (return)\n")); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SrpcClient::GetMethods() { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("SrpcClient::GetMethods (this=%p)\n", 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<void*>(this))); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NULL == srpc_channel_.client) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t method_count = NaClSrpcServiceMethodCount(srpc_channel_.client); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Intern the methods into a mapping from identifiers to MethodInfo. 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (uint32_t i = 0; i < method_count; ++i) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int retval; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* method_name; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* input_types; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* output_types; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) retval = NaClSrpcServiceMethodNameAndTypes(srpc_channel_.client, 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i, 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &method_name, 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &input_types, 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &output_types); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!retval) { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsValidIdentifierString(method_name, NULL)) { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If name is not an ECMAScript identifier, do not enter it into the 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // methods_ table. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MethodInfo* method_info = 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new MethodInfo(NULL, method_name, input_types, output_types, i); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NULL == method_info) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Install in the map only if successfully read. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) methods_[method_name] = method_info; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool SrpcClient::HasMethod(const std::string& method_name) { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_method = (NULL != methods_[method_name]); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(( 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SrpcClient::HasMethod (this=%p, method_name='%s', return %d)\n", 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<void*>(this), method_name.c_str(), has_method)); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return has_method; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool SrpcClient::InitParams(const std::string& method_name, 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SrpcParams* params) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MethodInfo* method_info = methods_[method_name]; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (method_info) { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return params->Init(method_info->ins(), method_info->outs()); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool SrpcClient::Invoke(const std::string& method_name, SrpcParams* params) { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It would be better if we could set the exception on each detailed failure 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // case. However, there are calls to Invoke from within the plugin itself, 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and these could leave residual exceptions pending. This seems to be 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // happening specifically with hard_shutdowns. 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("SrpcClient::Invoke (this=%p, method_name='%s', params=%p)\n", 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<void*>(this), 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_name.c_str(), 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<void*>(params))); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure Invoke was called with a method name that has a binding. 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NULL == methods_[method_name]) { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("SrpcClient::Invoke (ident not in methods_)\n")); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("SrpcClient::Invoke (sending the rpc)\n")); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Call the method 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_error_ = NaClSrpcInvokeV(&srpc_channel_, 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) methods_[method_name]->index(), 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params->ins(), 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params->outs()); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("SrpcClient::Invoke (response=%d)\n", last_error_)); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NACL_SRPC_RESULT_OK != last_error_) { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("SrpcClient::Invoke (err='%s', return 0)\n", 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClSrpcErrorString(last_error_))); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("SrpcClient::Invoke (return 1)\n")); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SrpcClient::AttachService(NaClSrpcService* service, void* instance_data) { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) srpc_channel_.server = service; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) srpc_channel_.server_instance_data = instance_data; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace plugin 200