2 * Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
7 #include "components/nacl/renderer/plugin/srpc_client.h"
11 #include "components/nacl/renderer/plugin/plugin.h"
12 #include "components/nacl/renderer/plugin/srpc_params.h"
13 #include "components/nacl/renderer/plugin/utility.h"
14 #include "native_client/src/shared/platform/nacl_log.h"
18 typedef bool (*RpcFunction
)(void* obj
, SrpcParams
* params
);
20 // MethodInfo records the method names and type signatures of an SRPC server.
23 // statically defined method - called through a pointer
24 MethodInfo(const RpcFunction function_ptr
,
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
),
39 free(reinterpret_cast<void*>(name_
));
40 free(reinterpret_cast<void*>(ins_
));
41 free(reinterpret_cast<void*>(outs_
));
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_
; }
51 NACL_DISALLOW_COPY_AND_ASSIGN(MethodInfo
);
52 RpcFunction function_ptr_
;
59 SrpcClient::SrpcClient()
60 : srpc_channel_initialised_(false) {
61 PLUGIN_PRINTF(("SrpcClient::SrpcClient (this=%p)\n",
62 static_cast<void*>(this)));
63 NaClSrpcChannelInitialize(&srpc_channel_
);
66 SrpcClient
* SrpcClient::New(nacl::DescWrapper
* wrapper
) {
67 nacl::scoped_ptr
<SrpcClient
> srpc_client(new SrpcClient());
68 if (!srpc_client
->Init(wrapper
)) {
69 PLUGIN_PRINTF(("SrpcClient::New (SrpcClient::Init failed)\n"));
72 return srpc_client
.release();
75 bool SrpcClient::Init(nacl::DescWrapper
* wrapper
) {
76 PLUGIN_PRINTF(("SrpcClient::Init (this=%p, wrapper=%p)\n",
77 static_cast<void*>(this),
78 static_cast<void*>(wrapper
)));
79 // Open the channel to pass RPC information back and forth
80 if (!NaClSrpcClientCtor(&srpc_channel_
, wrapper
->desc())) {
83 srpc_channel_initialised_
= true;
84 PLUGIN_PRINTF(("SrpcClient::Init (Ctor worked)\n"));
85 // Record the method names in a convenient way for later dispatches.
87 PLUGIN_PRINTF(("SrpcClient::Init (GetMethods worked)\n"));
91 SrpcClient::~SrpcClient() {
92 PLUGIN_PRINTF(("SrpcClient::~SrpcClient (this=%p, has_srpc_channel=%d)\n",
93 static_cast<void*>(this), srpc_channel_initialised_
));
94 // And delete the connection.
95 if (srpc_channel_initialised_
) {
96 PLUGIN_PRINTF(("SrpcClient::~SrpcClient (destroying srpc_channel)\n"));
97 NaClSrpcDtor(&srpc_channel_
);
99 for (Methods::iterator iter
= methods_
.begin();
100 iter
!= methods_
.end();
104 PLUGIN_PRINTF(("SrpcClient::~SrpcClient (return)\n"));
107 void SrpcClient::GetMethods() {
108 PLUGIN_PRINTF(("SrpcClient::GetMethods (this=%p)\n",
109 static_cast<void*>(this)));
110 if (NULL
== srpc_channel_
.client
) {
113 uint32_t method_count
= NaClSrpcServiceMethodCount(srpc_channel_
.client
);
114 // Intern the methods into a mapping from identifiers to MethodInfo.
115 for (uint32_t i
= 0; i
< method_count
; ++i
) {
117 const char* method_name
;
118 const char* input_types
;
119 const char* output_types
;
121 retval
= NaClSrpcServiceMethodNameAndTypes(srpc_channel_
.client
,
129 if (!IsValidIdentifierString(method_name
, NULL
)) {
130 // If name is not an ECMAScript identifier, do not enter it into the
134 MethodInfo
* method_info
=
135 new MethodInfo(NULL
, method_name
, input_types
, output_types
, i
);
136 if (NULL
== method_info
) {
139 // Install in the map only if successfully read.
140 methods_
[method_name
] = method_info
;
144 bool SrpcClient::HasMethod(const std::string
& method_name
) {
145 bool has_method
= (NULL
!= methods_
[method_name
]);
147 "SrpcClient::HasMethod (this=%p, method_name='%s', return %d)\n",
148 static_cast<void*>(this), method_name
.c_str(), has_method
));
152 bool SrpcClient::InitParams(const std::string
& method_name
,
153 SrpcParams
* params
) {
154 MethodInfo
* method_info
= methods_
[method_name
];
156 return params
->Init(method_info
->ins(), method_info
->outs());
161 bool SrpcClient::Invoke(const std::string
& method_name
, SrpcParams
* params
) {
162 // It would be better if we could set the exception on each detailed failure
163 // case. However, there are calls to Invoke from within the plugin itself,
164 // and these could leave residual exceptions pending. This seems to be
165 // happening specifically with hard_shutdowns.
166 PLUGIN_PRINTF(("SrpcClient::Invoke (this=%p, method_name='%s', params=%p)\n",
167 static_cast<void*>(this),
169 static_cast<void*>(params
)));
171 // Ensure Invoke was called with a method name that has a binding.
172 if (NULL
== methods_
[method_name
]) {
173 PLUGIN_PRINTF(("SrpcClient::Invoke (ident not in methods_)\n"));
177 PLUGIN_PRINTF(("SrpcClient::Invoke (sending the rpc)\n"));
179 last_error_
= NaClSrpcInvokeV(&srpc_channel_
,
180 methods_
[method_name
]->index(),
183 PLUGIN_PRINTF(("SrpcClient::Invoke (response=%d)\n", last_error_
));
184 if (NACL_SRPC_RESULT_OK
!= last_error_
) {
185 PLUGIN_PRINTF(("SrpcClient::Invoke (err='%s', return 0)\n",
186 NaClSrpcErrorString(last_error_
)));
190 PLUGIN_PRINTF(("SrpcClient::Invoke (return 1)\n"));
194 } // namespace plugin