| Index: ppapi/native_client/src/shared/ppapi_proxy/plugin_ppp_rpc_server.cc
|
| ===================================================================
|
| --- ppapi/native_client/src/shared/ppapi_proxy/plugin_ppp_rpc_server.cc (revision 0)
|
| +++ ppapi/native_client/src/shared/ppapi_proxy/plugin_ppp_rpc_server.cc (revision 0)
|
| @@ -0,0 +1,154 @@
|
| +// Copyright (c) 2010 The Native Client Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +//
|
| +// SRPC-abstraction wrappers around PPP functions.
|
| +
|
| +#include <stdarg.h>
|
| +
|
| +#include "native_client/src/include/portability.h"
|
| +#include "native_client/src/include/portability_process.h"
|
| +#include "native_client/src/shared/ppapi_proxy/plugin_globals.h"
|
| +#include "native_client/src/shared/ppapi_proxy/utility.h"
|
| +#include "native_client/src/shared/srpc/nacl_srpc.h"
|
| +#include "ppapi/c/ppp.h"
|
| +#include "srpcgen/ppp_rpc.h"
|
| +
|
| +using ppapi_proxy::DebugPrintf;
|
| +
|
| +namespace {
|
| +
|
| +const int kInvalidDesc = -1;
|
| +
|
| +// In order to close the upcall socket descriptor when we shut down, we
|
| +// need to remember it.
|
| +// TODO(sehr,polina): This ugly state should be attached to the correct
|
| +// data structure for the plugin module.
|
| +int upcall_socket_fd = kInvalidDesc;
|
| +
|
| +// The plugin will make synchronous calls back to the browser on the main
|
| +// thread. The service exported from the browser is specified in
|
| +// service_description.
|
| +bool StartMainSrpcChannel(const char* service_description,
|
| + NaClSrpcChannel* channel) {
|
| + NaClSrpcService* service =
|
| + reinterpret_cast<NaClSrpcService*>(calloc(1, sizeof(*service)));
|
| + if (NULL == service) {
|
| + return false;
|
| + }
|
| + if (!NaClSrpcServiceStringCtor(service, service_description)) {
|
| + free(service);
|
| + return false;
|
| + }
|
| + channel->client = service;
|
| + // Remember the main channel for later calls back from the main thread.
|
| + ppapi_proxy::SetMainSrpcChannel(channel);
|
| + return true;
|
| +}
|
| +
|
| +void StopMainSrpcChannel() {
|
| + NaClSrpcChannel* channel = ppapi_proxy::GetMainSrpcChannel();
|
| + NaClSrpcService* service = channel->client;
|
| + NaClSrpcServiceDtor(service);
|
| + channel->client = NULL;
|
| + ppapi_proxy::SetMainSrpcChannel(NULL);
|
| +}
|
| +
|
| +// The plugin will make asynchronous calls to the browser on other threads.
|
| +// The service exported on this channel will be gotten by service discovery.
|
| +bool StartUpcallSrpcChannel(NaClSrpcImcDescType upcall_channel_desc) {
|
| + // Create the upcall srpc client.
|
| + if (upcall_channel_desc == kInvalidDesc) {
|
| + return false;
|
| + }
|
| + NaClSrpcChannel* upcall_channel = reinterpret_cast<NaClSrpcChannel*>(
|
| + calloc(1, sizeof(*upcall_channel)));
|
| + if (NULL == upcall_channel) {
|
| + return false;
|
| + }
|
| + if (!NaClSrpcClientCtor(upcall_channel, upcall_channel_desc)) {
|
| + free(upcall_channel);
|
| + return false;
|
| + }
|
| + ppapi_proxy::SetUpcallSrpcChannel(upcall_channel);
|
| + upcall_socket_fd = upcall_channel_desc;
|
| + return true;
|
| +}
|
| +
|
| +void StopUpcallSrpcChannel() {
|
| + NaClSrpcChannel* upcall_channel = ppapi_proxy::GetUpcallSrpcChannel();
|
| + NaClSrpcDtor(upcall_channel);
|
| + ppapi_proxy::SetUpcallSrpcChannel(NULL);
|
| + close(upcall_socket_fd);
|
| + upcall_socket_fd = kInvalidDesc;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +//
|
| +// The following methods are the SRPC dispatchers for ppapi/c/ppp.h.
|
| +//
|
| +
|
| +void PppRpcServer::PPP_InitializeModule(
|
| + NaClSrpcRpc* rpc,
|
| + NaClSrpcClosure* done,
|
| + int32_t pid,
|
| + PP_Module module,
|
| + NaClSrpcImcDescType upcall_channel_desc,
|
| + char* service_description,
|
| + int32_t* nacl_pid,
|
| + int32_t* success) {
|
| + NaClSrpcClosureRunner runner(done);
|
| + rpc->result = NACL_SRPC_RESULT_APP_ERROR;
|
| + DebugPrintf("PPP_InitializeModule: module=%"NACL_PRIu32": %s\n",
|
| + module, service_description);
|
| + // Set up the service for calling back into the browser.
|
| + if (!StartMainSrpcChannel(const_cast<const char*>(service_description),
|
| + rpc->channel)) {
|
| + DebugPrintf("PPP_InitializeModule: "
|
| + "failed to export service on main channel\n");
|
| + return;
|
| + }
|
| + // Set up the upcall channel for calling back into the browser.
|
| + if (!StartUpcallSrpcChannel(upcall_channel_desc)) {
|
| + DebugPrintf("PPP_InitializeModule: "
|
| + "failed to construct upcall channel\n");
|
| + StopMainSrpcChannel();
|
| + return;
|
| + }
|
| + ppapi_proxy::SetModuleIdForSrpcChannel(rpc->channel, module);
|
| + *success = ::PPP_InitializeModule(module, ppapi_proxy::GetBrowserInterface);
|
| + *nacl_pid = GETPID();
|
| + rpc->result = NACL_SRPC_RESULT_OK;
|
| +}
|
| +
|
| +void PppRpcServer::PPP_ShutdownModule(NaClSrpcRpc* rpc,
|
| + NaClSrpcClosure* done) {
|
| + NaClSrpcClosureRunner runner(done);
|
| + rpc->result = NACL_SRPC_RESULT_APP_ERROR;
|
| + DebugPrintf("PPP_ShutdownModule\n");
|
| + // We do NOT call ::PPP_ShutdownModule as it cannot do anything useful
|
| + // at this point while still having an ability to hang the browser.
|
| + ppapi_proxy::UnsetModuleIdForSrpcChannel(rpc->channel);
|
| + StopUpcallSrpcChannel();
|
| + // TODO(sehr, polina): do we even need this function?
|
| + // Shouldn't the Dtor be called when nexe's main exits?
|
| + //StopMainSrpcChannel();
|
| + // Exit the srpc loop. The server won't answer any more requests.
|
| + rpc->result = NACL_SRPC_RESULT_BREAK;
|
| + DebugPrintf("PPP_ShutdownModule: %s\n", NaClSrpcErrorString(rpc->result));
|
| +}
|
| +
|
| +void PppRpcServer::PPP_GetInterface(NaClSrpcRpc* rpc,
|
| + NaClSrpcClosure* done,
|
| + char* interface_name,
|
| + int32_t* exports_interface_name) {
|
| + NaClSrpcClosureRunner runner(done);
|
| + rpc->result = NACL_SRPC_RESULT_APP_ERROR;
|
| + DebugPrintf("PPP_GetInterface('%s')\n", interface_name);
|
| + // Since the proxy will make calls to proxied interfaces, we need simply
|
| + // to know whether the plugin exports a given interface.
|
| + const void* plugin_interface = ::PPP_GetInterface(interface_name);
|
| + *exports_interface_name = (plugin_interface != NULL);
|
| + rpc->result = NACL_SRPC_RESULT_OK;
|
| +}
|
|
|