OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2008 The Native Client Authors. All rights reserved. | |
3 * Use of this source code is governed by a BSD-style license that can | |
4 * be found in the LICENSE file. | |
5 */ | |
6 | |
7 | |
8 #include <string.h> | |
9 | |
10 #include <map> | |
11 | |
12 #include "native_client/src/shared/platform/nacl_log.h" | |
13 #include "native_client/src/shared/npruntime/npmodule.h" | |
14 | |
15 #include "native_client/src/trusted/plugin/srpc/browser_interface.h" | |
16 #include "native_client/src/trusted/plugin/srpc/connected_socket.h" | |
17 #include "native_client/src/trusted/plugin/srpc/scriptable_handle.h" | |
18 #include "native_client/src/trusted/plugin/srpc/srpc_client.h" | |
19 #include "native_client/src/trusted/plugin/srpc/utility.h" | |
20 #include "native_client/src/trusted/plugin/srpc/desc_based_handle.h" | |
21 | |
22 namespace { | |
23 | |
24 // TODO(sehr): again, not reentrant. See bug 605. | |
25 PLUGIN_JMPBUF srpc_env; | |
26 | |
27 void SignalHandler(int value) { | |
28 PLUGIN_PRINTF(("SrpcClient::SignalHandler()\n")); | |
29 PLUGIN_LONGJMP(srpc_env, value); | |
30 } | |
31 | |
32 } // namespace | |
33 | |
34 namespace plugin { | |
35 | |
36 SrpcClient::SrpcClient() | |
37 : browser_interface_(NULL) { | |
38 PLUGIN_PRINTF(("SrpcClient::SrpcClient(%p)\n", | |
39 static_cast<void*>(this))); | |
40 } | |
41 | |
42 bool SrpcClient::Init(BrowserInterface* browser_interface, | |
43 ConnectedSocket* socket) { | |
44 PLUGIN_PRINTF(("SrpcClient::SrpcClient(%p, %p, %p)\n", | |
45 static_cast<void*>(this), | |
46 static_cast<void*>(browser_interface), | |
47 static_cast<void*>(socket))); | |
48 // Open the channel to pass RPC information back and forth | |
49 if (!NaClSrpcClientCtor(&srpc_channel_, socket->wrapper()->desc())) { | |
50 return false; | |
51 } | |
52 browser_interface_ = browser_interface; | |
53 PLUGIN_PRINTF(("SrpcClient::SrpcClient: Ctor worked\n")); | |
54 // Record the method names in a convenient way for later dispatches. | |
55 GetMethods(); | |
56 PLUGIN_PRINTF(("SrpcClient::SrpcClient: GetMethods worked\n")); | |
57 return true; | |
58 } | |
59 | |
60 SrpcClient::~SrpcClient() { | |
61 PLUGIN_PRINTF(("SrpcClient::~SrpcClient(%p)\n", static_cast<void*>(this))); | |
62 PLUGIN_PRINTF(("SrpcClient::~SrpcClient: destroying the channel\n")); | |
63 // And delete the connection. | |
64 NaClSrpcDtor(&srpc_channel_); | |
65 PLUGIN_PRINTF(("SrpcClient::~SrpcClient: done\n")); | |
66 } | |
67 | |
68 void SrpcClient::StartJSObjectProxy(Plugin* plugin) { | |
69 // TODO(sehr): this needs to be revisited when we allow groups of instances | |
70 // in one NaCl module. | |
71 uintptr_t npapi_ident = | |
72 browser_interface_->StringToIdentifier("NP_Initialize"); | |
73 if (methods_.find(npapi_ident) != methods_.end()) { | |
74 PLUGIN_PRINTF(("SrpcClient::SrpcClient: Is an NPAPI plugin\n")); | |
75 // Start up NPAPI interaction. | |
76 plugin->StartProxiedExecution(&srpc_channel_); | |
77 } | |
78 // TODO(polina,sehr): this also needs to be revisited for PPAPI proxying. | |
79 } | |
80 | |
81 void SrpcClient::GetMethods() { | |
82 PLUGIN_PRINTF(("SrpcClient::GetMethods(%p)\n", static_cast<void*>(this))); | |
83 if (NULL == srpc_channel_.client) { | |
84 return; | |
85 } | |
86 uint32_t method_count = NaClSrpcServiceMethodCount(srpc_channel_.client); | |
87 // Intern the methods into a mapping from NPIdentifiers to MethodInfo. | |
88 for (uint32_t i = 0; i < method_count; ++i) { | |
89 int retval; | |
90 const char* name; | |
91 const char* input_types; | |
92 const char* output_types; | |
93 | |
94 retval = NaClSrpcServiceMethodNameAndTypes(srpc_channel_.client, | |
95 i, | |
96 &name, | |
97 &input_types, | |
98 &output_types); | |
99 if (!IsValidIdentifierString(name, NULL)) { | |
100 // If name is not an ECMAScript identifier, do not enter it into the | |
101 // methods_ table. | |
102 continue; | |
103 } | |
104 uintptr_t ident = browser_interface_->StringToIdentifier(name); | |
105 MethodInfo* method_info = new(std::nothrow) MethodInfo(NULL, | |
106 name, | |
107 input_types, | |
108 output_types, | |
109 i); | |
110 if (NULL == method_info) { | |
111 return; | |
112 } | |
113 // Install in the map only if successfully read. | |
114 methods_[ident] = method_info; | |
115 } | |
116 } | |
117 | |
118 bool SrpcClient::HasMethod(uintptr_t method_id) { | |
119 PLUGIN_PRINTF(("SrpcClient::HasMethod(%p, %s)\n", | |
120 static_cast<void*>(this), | |
121 browser_interface_->IdentifierToString(method_id).c_str())); | |
122 return NULL != methods_[method_id]; | |
123 } | |
124 | |
125 bool SrpcClient::InitParams(uintptr_t method_id, SrpcParams* params) { | |
126 MethodInfo* method_info = methods_[method_id]; | |
127 if (method_info) { | |
128 return params->Init(method_info->ins(), method_info->outs()); | |
129 } | |
130 return false; | |
131 } | |
132 | |
133 bool SrpcClient::Invoke(uintptr_t method_id, | |
134 SrpcParams* params) { | |
135 // It would be better if we could set the exception on each detailed failure | |
136 // case. However, there are calls to Invoke from within the plugin itself, | |
137 // and these could leave residual exceptions pending. This seems to be | |
138 // happening specifically with hard_shutdowns. | |
139 PLUGIN_PRINTF(("SrpcClient::Invoke(%p, %s, %p)\n", | |
140 static_cast<void*>(this), | |
141 browser_interface_->IdentifierToString(method_id).c_str(), | |
142 static_cast<void*>(params))); | |
143 | |
144 // Ensure Invoke was called with an identifier that had a binding. | |
145 if (NULL == methods_[method_id]) { | |
146 PLUGIN_PRINTF(("SrpcClient::Invoke: ident not in methods_\n")); | |
147 return false; | |
148 } | |
149 | |
150 // Catch signals from SRPC/IMC/etc. | |
151 ScopedCatchSignals sigcatcher( | |
152 (ScopedCatchSignals::SigHandlerType) SignalHandler); | |
153 | |
154 PLUGIN_PRINTF(("SrpcClient::Invoke: sending the rpc\n")); | |
155 // Call the method | |
156 NaClSrpcError err = NaClSrpcInvokeV(&srpc_channel_, | |
157 methods_[method_id]->index(), | |
158 params->ins(), | |
159 params->outs()); | |
160 PLUGIN_PRINTF(("SrpcClient::Invoke: got response %d\n", err)); | |
161 if (NACL_SRPC_RESULT_OK != err) { | |
162 PLUGIN_PRINTF(("SrpcClient::Invoke: returned err %s\n", | |
163 NaClSrpcErrorString(err))); | |
164 return false; | |
165 } | |
166 | |
167 PLUGIN_PRINTF(("SrpcClient::Invoke: done\n")); | |
168 return true; | |
169 } | |
170 | |
171 } // namespace plugin | |
OLD | NEW |