| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 * Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 #include "native_client/src/trusted/plugin/srpc_client.h" |
| 7 | 8 |
| 8 #include <string.h> | 9 #include <string.h> |
| 9 | 10 |
| 10 #include <map> | |
| 11 | |
| 12 #include "native_client/src/shared/platform/nacl_log.h" | 11 #include "native_client/src/shared/platform/nacl_log.h" |
| 13 #include "native_client/src/trusted/plugin/browser_interface.h" | |
| 14 #include "native_client/src/trusted/plugin/desc_based_handle.h" | |
| 15 #include "native_client/src/trusted/plugin/plugin.h" | 12 #include "native_client/src/trusted/plugin/plugin.h" |
| 16 #include "native_client/src/trusted/plugin/scriptable_handle.h" | 13 #include "native_client/src/trusted/plugin/srpc_params.h" |
| 17 #include "native_client/src/trusted/plugin/srpc_client.h" | |
| 18 #include "native_client/src/trusted/plugin/utility.h" | 14 #include "native_client/src/trusted/plugin/utility.h" |
| 19 | 15 |
| 20 namespace plugin { | 16 namespace plugin { |
| 21 | 17 |
| 18 typedef bool (*RpcFunction)(void* obj, SrpcParams* params); |
| 19 |
| 20 // MethodInfo records the method names and type signatures of an SRPC server. |
| 21 class MethodInfo { |
| 22 public: |
| 23 // statically defined method - called through a pointer |
| 24 MethodInfo(const RpcFunction function_ptr, |
| 25 const char* name, |
| 26 const char* ins, |
| 27 const char* outs, |
| 28 // index is set to UINT_MAX for methods implemented by the plugin, |
| 29 // All methods implemented by nacl modules have indexes |
| 30 // that are lower than UINT_MAX. |
| 31 const uint32_t index = UINT_MAX) : |
| 32 function_ptr_(function_ptr), |
| 33 name_(STRDUP(name)), |
| 34 ins_(STRDUP(ins)), |
| 35 outs_(STRDUP(outs)), |
| 36 index_(index) { } |
| 37 |
| 38 ~MethodInfo() { |
| 39 free(reinterpret_cast<void*>(name_)); |
| 40 free(reinterpret_cast<void*>(ins_)); |
| 41 free(reinterpret_cast<void*>(outs_)); |
| 42 } |
| 43 |
| 44 RpcFunction function_ptr() const { return function_ptr_; } |
| 45 char* name() const { return name_; } |
| 46 char* ins() const { return ins_; } |
| 47 char* outs() const { return outs_; } |
| 48 uint32_t index() const { return index_; } |
| 49 |
| 50 private: |
| 51 NACL_DISALLOW_COPY_AND_ASSIGN(MethodInfo); |
| 52 RpcFunction function_ptr_; |
| 53 char* name_; |
| 54 char* ins_; |
| 55 char* outs_; |
| 56 uint32_t index_; |
| 57 }; |
| 58 |
| 22 SrpcClient::SrpcClient() | 59 SrpcClient::SrpcClient() |
| 23 : srpc_channel_initialised_(false), | 60 : srpc_channel_initialised_(false) { |
| 24 browser_interface_(NULL) { | |
| 25 PLUGIN_PRINTF(("SrpcClient::SrpcClient (this=%p)\n", | 61 PLUGIN_PRINTF(("SrpcClient::SrpcClient (this=%p)\n", |
| 26 static_cast<void*>(this))); | 62 static_cast<void*>(this))); |
| 27 NaClSrpcChannelInitialize(&srpc_channel_); | 63 NaClSrpcChannelInitialize(&srpc_channel_); |
| 28 } | 64 } |
| 29 | 65 |
| 30 SrpcClient* SrpcClient::New(Plugin* plugin, nacl::DescWrapper* wrapper) { | 66 SrpcClient* SrpcClient::New(nacl::DescWrapper* wrapper) { |
| 31 nacl::scoped_ptr<SrpcClient> srpc_client(new SrpcClient()); | 67 nacl::scoped_ptr<SrpcClient> srpc_client(new SrpcClient()); |
| 32 if (!srpc_client->Init(plugin->browser_interface(), wrapper)) { | 68 if (!srpc_client->Init(wrapper)) { |
| 33 PLUGIN_PRINTF(("SrpcClient::New (SrpcClient::Init failed)\n")); | 69 PLUGIN_PRINTF(("SrpcClient::New (SrpcClient::Init failed)\n")); |
| 34 return NULL; | 70 return NULL; |
| 35 } | 71 } |
| 36 return srpc_client.release(); | 72 return srpc_client.release(); |
| 37 } | 73 } |
| 38 | 74 |
| 39 bool SrpcClient::Init(BrowserInterface* browser_interface, | 75 bool SrpcClient::Init(nacl::DescWrapper* wrapper) { |
| 40 nacl::DescWrapper* wrapper) { | 76 PLUGIN_PRINTF(("SrpcClient::Init (this=%p, wrapper=%p)\n", |
| 41 PLUGIN_PRINTF(("SrpcClient::Init (this=%p, browser_interface=%p, wrapper=%p)" | 77 static_cast<void*>(this), |
| 42 "\n", static_cast<void*>(this), | |
| 43 static_cast<void*>(browser_interface), | |
| 44 static_cast<void*>(wrapper))); | 78 static_cast<void*>(wrapper))); |
| 45 // Open the channel to pass RPC information back and forth | 79 // Open the channel to pass RPC information back and forth |
| 46 if (!NaClSrpcClientCtor(&srpc_channel_, wrapper->desc())) { | 80 if (!NaClSrpcClientCtor(&srpc_channel_, wrapper->desc())) { |
| 47 return false; | 81 return false; |
| 48 } | 82 } |
| 49 srpc_channel_initialised_ = true; | 83 srpc_channel_initialised_ = true; |
| 50 browser_interface_ = browser_interface; | |
| 51 PLUGIN_PRINTF(("SrpcClient::Init (Ctor worked)\n")); | 84 PLUGIN_PRINTF(("SrpcClient::Init (Ctor worked)\n")); |
| 52 // Record the method names in a convenient way for later dispatches. | 85 // Record the method names in a convenient way for later dispatches. |
| 53 GetMethods(); | 86 GetMethods(); |
| 54 PLUGIN_PRINTF(("SrpcClient::Init (GetMethods worked)\n")); | 87 PLUGIN_PRINTF(("SrpcClient::Init (GetMethods worked)\n")); |
| 55 return true; | 88 return true; |
| 56 } | 89 } |
| 57 | 90 |
| 58 SrpcClient::~SrpcClient() { | 91 SrpcClient::~SrpcClient() { |
| 59 PLUGIN_PRINTF(("SrpcClient::~SrpcClient (this=%p, has_srpc_channel=%d)\n", | 92 PLUGIN_PRINTF(("SrpcClient::~SrpcClient (this=%p, has_srpc_channel=%d)\n", |
| 60 static_cast<void*>(this), srpc_channel_initialised_)); | 93 static_cast<void*>(this), srpc_channel_initialised_)); |
| 61 // And delete the connection. | 94 // And delete the connection. |
| 62 if (srpc_channel_initialised_) { | 95 if (srpc_channel_initialised_) { |
| 63 PLUGIN_PRINTF(("SrpcClient::~SrpcClient (destroying srpc_channel)\n")); | 96 PLUGIN_PRINTF(("SrpcClient::~SrpcClient (destroying srpc_channel)\n")); |
| 64 NaClSrpcDtor(&srpc_channel_); | 97 NaClSrpcDtor(&srpc_channel_); |
| 65 } | 98 } |
| 66 for (Methods::iterator iter = methods_.begin(); | 99 for (Methods::iterator iter = methods_.begin(); |
| 67 iter != methods_.end(); | 100 iter != methods_.end(); |
| 68 ++iter) { | 101 ++iter) { |
| 69 delete iter->second; | 102 delete iter->second; |
| 70 } | 103 } |
| 71 PLUGIN_PRINTF(("SrpcClient::~SrpcClient (return)\n")); | 104 PLUGIN_PRINTF(("SrpcClient::~SrpcClient (return)\n")); |
| 72 } | 105 } |
| 73 | 106 |
| 74 bool SrpcClient::StartJSObjectProxy(Plugin* plugin, | 107 bool SrpcClient::StartJSObjectProxy(Plugin* plugin, ErrorInfo *error_info) { |
| 75 ErrorInfo *error_info) { | |
| 76 // Start up PPAPI interaction if the plugin determines that the | 108 // Start up PPAPI interaction if the plugin determines that the |
| 77 // requisite methods are exported. | 109 // requisite methods are exported. |
| 78 return plugin->StartProxiedExecution(&srpc_channel_, error_info); | 110 return plugin->StartProxiedExecution(&srpc_channel_, error_info); |
| 79 } | 111 } |
| 80 | 112 |
| 81 void SrpcClient::GetMethods() { | 113 void SrpcClient::GetMethods() { |
| 82 PLUGIN_PRINTF(("SrpcClient::GetMethods (this=%p)\n", | 114 PLUGIN_PRINTF(("SrpcClient::GetMethods (this=%p)\n", |
| 83 static_cast<void*>(this))); | 115 static_cast<void*>(this))); |
| 84 if (NULL == srpc_channel_.client) { | 116 if (NULL == srpc_channel_.client) { |
| 85 return; | 117 return; |
| 86 } | 118 } |
| 87 uint32_t method_count = NaClSrpcServiceMethodCount(srpc_channel_.client); | 119 uint32_t method_count = NaClSrpcServiceMethodCount(srpc_channel_.client); |
| 88 // Intern the methods into a mapping from identifiers to MethodInfo. | 120 // Intern the methods into a mapping from identifiers to MethodInfo. |
| 89 for (uint32_t i = 0; i < method_count; ++i) { | 121 for (uint32_t i = 0; i < method_count; ++i) { |
| 90 int retval; | 122 int retval; |
| 91 const char* name; | 123 const char* method_name; |
| 92 const char* input_types; | 124 const char* input_types; |
| 93 const char* output_types; | 125 const char* output_types; |
| 94 | 126 |
| 95 retval = NaClSrpcServiceMethodNameAndTypes(srpc_channel_.client, | 127 retval = NaClSrpcServiceMethodNameAndTypes(srpc_channel_.client, |
| 96 i, | 128 i, |
| 97 &name, | 129 &method_name, |
| 98 &input_types, | 130 &input_types, |
| 99 &output_types); | 131 &output_types); |
| 100 if (!retval) { | 132 if (!retval) { |
| 101 return; | 133 return; |
| 102 } | 134 } |
| 103 if (!IsValidIdentifierString(name, NULL)) { | 135 if (!IsValidIdentifierString(method_name, NULL)) { |
| 104 // If name is not an ECMAScript identifier, do not enter it into the | 136 // If name is not an ECMAScript identifier, do not enter it into the |
| 105 // methods_ table. | 137 // methods_ table. |
| 106 continue; | 138 continue; |
| 107 } | 139 } |
| 108 uintptr_t ident = browser_interface_->StringToIdentifier(name); | |
| 109 MethodInfo* method_info = | 140 MethodInfo* method_info = |
| 110 new MethodInfo(NULL, name, input_types, output_types, i); | 141 new MethodInfo(NULL, method_name, input_types, output_types, i); |
| 111 if (NULL == method_info) { | 142 if (NULL == method_info) { |
| 112 return; | 143 return; |
| 113 } | 144 } |
| 114 // Install in the map only if successfully read. | 145 // Install in the map only if successfully read. |
| 115 methods_[ident] = method_info; | 146 methods_[method_name] = method_info; |
| 116 } | 147 } |
| 117 } | 148 } |
| 118 | 149 |
| 119 bool SrpcClient::HasMethod(uintptr_t method_id) { | 150 bool SrpcClient::HasMethod(const nacl::string& method_name) { |
| 120 bool has_method = (NULL != methods_[method_id]); | 151 bool has_method = (NULL != methods_[method_name]); |
| 121 PLUGIN_PRINTF(("SrpcClient::HasMethod (this=%p, return %d)\n", | 152 PLUGIN_PRINTF(( |
| 122 static_cast<void*>(this), has_method)); | 153 "SrpcClient::HasMethod (this=%p, method_name='%s', return %d)\n", |
| 154 static_cast<void*>(this), method_name.c_str(), has_method)); |
| 123 return has_method; | 155 return has_method; |
| 124 } | 156 } |
| 125 | 157 |
| 126 bool SrpcClient::InitParams(uintptr_t method_id, SrpcParams* params) { | 158 bool SrpcClient::InitParams(const nacl::string& method_name, |
| 127 MethodInfo* method_info = methods_[method_id]; | 159 SrpcParams* params) { |
| 160 MethodInfo* method_info = methods_[method_name]; |
| 128 if (method_info) { | 161 if (method_info) { |
| 129 return params->Init(method_info->ins(), method_info->outs()); | 162 return params->Init(method_info->ins(), method_info->outs()); |
| 130 } | 163 } |
| 131 return false; | 164 return false; |
| 132 } | 165 } |
| 133 | 166 |
| 134 bool SrpcClient::Invoke(uintptr_t method_id, | 167 bool SrpcClient::Invoke(const nacl::string& method_name, SrpcParams* params) { |
| 135 SrpcParams* params) { | |
| 136 // It would be better if we could set the exception on each detailed failure | 168 // It would be better if we could set the exception on each detailed failure |
| 137 // case. However, there are calls to Invoke from within the plugin itself, | 169 // case. However, there are calls to Invoke from within the plugin itself, |
| 138 // and these could leave residual exceptions pending. This seems to be | 170 // and these could leave residual exceptions pending. This seems to be |
| 139 // happening specifically with hard_shutdowns. | 171 // happening specifically with hard_shutdowns. |
| 140 PLUGIN_PRINTF(("SrpcClient::Invoke (this=%p, method_name='%s', params=%p)\n", | 172 PLUGIN_PRINTF(("SrpcClient::Invoke (this=%p, method_name='%s', params=%p)\n", |
| 141 static_cast<void*>(this), | 173 static_cast<void*>(this), |
| 142 browser_interface_->IdentifierToString(method_id).c_str(), | 174 method_name.c_str(), |
| 143 static_cast<void*>(params))); | 175 static_cast<void*>(params))); |
| 144 | 176 |
| 145 // Ensure Invoke was called with an identifier that had a binding. | 177 // Ensure Invoke was called with a method name that has a binding. |
| 146 if (NULL == methods_[method_id]) { | 178 if (NULL == methods_[method_name]) { |
| 147 PLUGIN_PRINTF(("SrpcClient::Invoke (ident not in methods_)\n")); | 179 PLUGIN_PRINTF(("SrpcClient::Invoke (ident not in methods_)\n")); |
| 148 return false; | 180 return false; |
| 149 } | 181 } |
| 150 | 182 |
| 151 PLUGIN_PRINTF(("SrpcClient::Invoke (sending the rpc)\n")); | 183 PLUGIN_PRINTF(("SrpcClient::Invoke (sending the rpc)\n")); |
| 152 // Call the method | 184 // Call the method |
| 153 NaClSrpcError err = NaClSrpcInvokeV(&srpc_channel_, | 185 NaClSrpcError err = NaClSrpcInvokeV(&srpc_channel_, |
| 154 methods_[method_id]->index(), | 186 methods_[method_name]->index(), |
| 155 params->ins(), | 187 params->ins(), |
| 156 params->outs()); | 188 params->outs()); |
| 157 PLUGIN_PRINTF(("SrpcClient::Invoke (response=%d)\n", err)); | 189 PLUGIN_PRINTF(("SrpcClient::Invoke (response=%d)\n", err)); |
| 158 if (NACL_SRPC_RESULT_OK != err) { | 190 if (NACL_SRPC_RESULT_OK != err) { |
| 159 PLUGIN_PRINTF(("SrpcClient::Invoke (err='%s', return 0)\n", | 191 PLUGIN_PRINTF(("SrpcClient::Invoke (err='%s', return 0)\n", |
| 160 NaClSrpcErrorString(err))); | 192 NaClSrpcErrorString(err))); |
| 161 return false; | 193 return false; |
| 162 } | 194 } |
| 163 | 195 |
| 164 PLUGIN_PRINTF(("SrpcClient::Invoke (return 1)\n")); | 196 PLUGIN_PRINTF(("SrpcClient::Invoke (return 1)\n")); |
| 165 return true; | 197 return true; |
| 166 } | 198 } |
| 167 | 199 |
| 168 void SrpcClient::AttachService(NaClSrpcService* service, void* instance_data) { | 200 void SrpcClient::AttachService(NaClSrpcService* service, void* instance_data) { |
| 169 srpc_channel_.server = service; | 201 srpc_channel_.server = service; |
| 170 srpc_channel_.server_instance_data = instance_data; | 202 srpc_channel_.server_instance_data = instance_data; |
| 171 } | 203 } |
| 172 | 204 |
| 173 } // namespace plugin | 205 } // namespace plugin |
| OLD | NEW |