OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 The Native Client Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 // |
| 5 // SRPC-abstraction wrappers around PPP functions. |
| 6 |
| 7 #include <stdarg.h> |
| 8 |
| 9 #include "native_client/src/include/portability.h" |
| 10 #include "native_client/src/include/portability_process.h" |
| 11 #include "native_client/src/shared/ppapi_proxy/plugin_globals.h" |
| 12 #include "native_client/src/shared/ppapi_proxy/utility.h" |
| 13 #include "native_client/src/shared/srpc/nacl_srpc.h" |
| 14 #include "ppapi/c/ppp.h" |
| 15 #include "srpcgen/ppp_rpc.h" |
| 16 |
| 17 using ppapi_proxy::DebugPrintf; |
| 18 |
| 19 namespace { |
| 20 |
| 21 const int kInvalidDesc = -1; |
| 22 |
| 23 // In order to close the upcall socket descriptor when we shut down, we |
| 24 // need to remember it. |
| 25 // TODO(sehr,polina): This ugly state should be attached to the correct |
| 26 // data structure for the plugin module. |
| 27 int upcall_socket_fd = kInvalidDesc; |
| 28 |
| 29 // The plugin will make synchronous calls back to the browser on the main |
| 30 // thread. The service exported from the browser is specified in |
| 31 // service_description. |
| 32 bool StartMainSrpcChannel(const char* service_description, |
| 33 NaClSrpcChannel* channel) { |
| 34 NaClSrpcService* service = |
| 35 reinterpret_cast<NaClSrpcService*>(calloc(1, sizeof(*service))); |
| 36 if (NULL == service) { |
| 37 return false; |
| 38 } |
| 39 if (!NaClSrpcServiceStringCtor(service, service_description)) { |
| 40 free(service); |
| 41 return false; |
| 42 } |
| 43 channel->client = service; |
| 44 // Remember the main channel for later calls back from the main thread. |
| 45 ppapi_proxy::SetMainSrpcChannel(channel); |
| 46 return true; |
| 47 } |
| 48 |
| 49 void StopMainSrpcChannel() { |
| 50 NaClSrpcChannel* channel = ppapi_proxy::GetMainSrpcChannel(); |
| 51 NaClSrpcService* service = channel->client; |
| 52 NaClSrpcServiceDtor(service); |
| 53 channel->client = NULL; |
| 54 ppapi_proxy::SetMainSrpcChannel(NULL); |
| 55 } |
| 56 |
| 57 // The plugin will make asynchronous calls to the browser on other threads. |
| 58 // The service exported on this channel will be gotten by service discovery. |
| 59 bool StartUpcallSrpcChannel(NaClSrpcImcDescType upcall_channel_desc) { |
| 60 // Create the upcall srpc client. |
| 61 if (upcall_channel_desc == kInvalidDesc) { |
| 62 return false; |
| 63 } |
| 64 NaClSrpcChannel* upcall_channel = reinterpret_cast<NaClSrpcChannel*>( |
| 65 calloc(1, sizeof(*upcall_channel))); |
| 66 if (NULL == upcall_channel) { |
| 67 return false; |
| 68 } |
| 69 if (!NaClSrpcClientCtor(upcall_channel, upcall_channel_desc)) { |
| 70 free(upcall_channel); |
| 71 return false; |
| 72 } |
| 73 ppapi_proxy::SetUpcallSrpcChannel(upcall_channel); |
| 74 upcall_socket_fd = upcall_channel_desc; |
| 75 return true; |
| 76 } |
| 77 |
| 78 void StopUpcallSrpcChannel() { |
| 79 NaClSrpcChannel* upcall_channel = ppapi_proxy::GetUpcallSrpcChannel(); |
| 80 NaClSrpcDtor(upcall_channel); |
| 81 ppapi_proxy::SetUpcallSrpcChannel(NULL); |
| 82 close(upcall_socket_fd); |
| 83 upcall_socket_fd = kInvalidDesc; |
| 84 } |
| 85 |
| 86 } // namespace |
| 87 |
| 88 // |
| 89 // The following methods are the SRPC dispatchers for ppapi/c/ppp.h. |
| 90 // |
| 91 |
| 92 void PppRpcServer::PPP_InitializeModule( |
| 93 NaClSrpcRpc* rpc, |
| 94 NaClSrpcClosure* done, |
| 95 int32_t pid, |
| 96 PP_Module module, |
| 97 NaClSrpcImcDescType upcall_channel_desc, |
| 98 char* service_description, |
| 99 int32_t* nacl_pid, |
| 100 int32_t* success) { |
| 101 NaClSrpcClosureRunner runner(done); |
| 102 rpc->result = NACL_SRPC_RESULT_APP_ERROR; |
| 103 DebugPrintf("PPP_InitializeModule: module=%"NACL_PRIu32": %s\n", |
| 104 module, service_description); |
| 105 // Set up the service for calling back into the browser. |
| 106 if (!StartMainSrpcChannel(const_cast<const char*>(service_description), |
| 107 rpc->channel)) { |
| 108 DebugPrintf("PPP_InitializeModule: " |
| 109 "failed to export service on main channel\n"); |
| 110 return; |
| 111 } |
| 112 // Set up the upcall channel for calling back into the browser. |
| 113 if (!StartUpcallSrpcChannel(upcall_channel_desc)) { |
| 114 DebugPrintf("PPP_InitializeModule: " |
| 115 "failed to construct upcall channel\n"); |
| 116 StopMainSrpcChannel(); |
| 117 return; |
| 118 } |
| 119 ppapi_proxy::SetModuleIdForSrpcChannel(rpc->channel, module); |
| 120 *success = ::PPP_InitializeModule(module, ppapi_proxy::GetBrowserInterface); |
| 121 *nacl_pid = GETPID(); |
| 122 rpc->result = NACL_SRPC_RESULT_OK; |
| 123 } |
| 124 |
| 125 void PppRpcServer::PPP_ShutdownModule(NaClSrpcRpc* rpc, |
| 126 NaClSrpcClosure* done) { |
| 127 NaClSrpcClosureRunner runner(done); |
| 128 rpc->result = NACL_SRPC_RESULT_APP_ERROR; |
| 129 DebugPrintf("PPP_ShutdownModule\n"); |
| 130 // We do NOT call ::PPP_ShutdownModule as it cannot do anything useful |
| 131 // at this point while still having an ability to hang the browser. |
| 132 ppapi_proxy::UnsetModuleIdForSrpcChannel(rpc->channel); |
| 133 StopUpcallSrpcChannel(); |
| 134 // TODO(sehr, polina): do we even need this function? |
| 135 // Shouldn't the Dtor be called when nexe's main exits? |
| 136 //StopMainSrpcChannel(); |
| 137 // Exit the srpc loop. The server won't answer any more requests. |
| 138 rpc->result = NACL_SRPC_RESULT_BREAK; |
| 139 DebugPrintf("PPP_ShutdownModule: %s\n", NaClSrpcErrorString(rpc->result)); |
| 140 } |
| 141 |
| 142 void PppRpcServer::PPP_GetInterface(NaClSrpcRpc* rpc, |
| 143 NaClSrpcClosure* done, |
| 144 char* interface_name, |
| 145 int32_t* exports_interface_name) { |
| 146 NaClSrpcClosureRunner runner(done); |
| 147 rpc->result = NACL_SRPC_RESULT_APP_ERROR; |
| 148 DebugPrintf("PPP_GetInterface('%s')\n", interface_name); |
| 149 // Since the proxy will make calls to proxied interfaces, we need simply |
| 150 // to know whether the plugin exports a given interface. |
| 151 const void* plugin_interface = ::PPP_GetInterface(interface_name); |
| 152 *exports_interface_name = (plugin_interface != NULL); |
| 153 rpc->result = NACL_SRPC_RESULT_OK; |
| 154 } |
OLD | NEW |