LCOV - code coverage report
Current view: directory - src/trusted/reverse_service - reverse_service.cc (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 230 130 56.5 %
Date: 2012-02-16 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2011 The Native Client 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.
       5                 :  */
       6                 : 
       7                 : #include <string.h>
       8                 : 
       9                 : #include <limits>
      10                 : #include <string>
      11                 : 
      12                 : #include "native_client/src/trusted/reverse_service/reverse_service.h"
      13                 : 
      14                 : #include "native_client/src/include/nacl_compiler_annotations.h"
      15                 : #include "native_client/src/include/nacl_scoped_ptr.h"
      16                 : #include "native_client/src/include/portability_io.h"
      17                 : #include "native_client/src/shared/platform/nacl_check.h"
      18                 : #include "native_client/src/shared/platform/nacl_host_desc.h"
      19                 : #include "native_client/src/shared/platform/nacl_log.h"
      20                 : #include "native_client/src/shared/platform/nacl_sync.h"
      21                 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
      22                 : #include "native_client/src/shared/platform/nacl_threads.h"
      23                 : #include "native_client/src/shared/srpc/nacl_srpc.h"
      24                 : 
      25                 : #include "native_client/src/trusted/desc/nacl_desc_invalid.h"
      26                 : #include "native_client/src/trusted/desc/nacl_desc_io.h"
      27                 : 
      28                 : #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
      29                 : 
      30                 : namespace {
      31                 : 
      32                 : void Test(NaClSrpcRpc* rpc,
      33                 :           NaClSrpcArg** in_args,
      34                 :           NaClSrpcArg** out_args,
      35               0 :           NaClSrpcClosure* done) {
      36               0 :   char *msg = in_args[0]->arrays.str;
      37               0 :   NaClSrpcClosureRunner on_return(done);
      38                 : 
      39                 :   UNREFERENCED_PARAMETER(out_args);
      40                 :   // use rpc->channel rather than rpc->channel->server_instance_data
      41                 :   // to show that Test RPCs arrive in different channels.
      42                 :   NaClLog(1, "Test: [%"NACL_PRIxPTR"] %s\n",
      43               0 :           reinterpret_cast<uintptr_t>(rpc->channel), msg);
      44               0 :   rpc->result = NACL_SRPC_RESULT_OK;
      45               0 : }
      46                 : 
      47                 : void AddChannel(NaClSrpcRpc* rpc,
      48                 :                 NaClSrpcArg** in_args,
      49                 :                 NaClSrpcArg** out_args,
      50               3 :                 NaClSrpcClosure* done) {
      51                 :   nacl::ReverseService* service = reinterpret_cast<nacl::ReverseService*>(
      52               3 :       rpc->channel->server_instance_data);
      53               3 :   NaClSrpcClosureRunner on_return(done);
      54                 : 
      55                 :   UNREFERENCED_PARAMETER(in_args);
      56                 : 
      57               3 :   NaClLog(4, "Entered AddChannel\n");
      58               3 :   out_args[0]->u.bval = service->Start(false);
      59               3 :   NaClLog(4, "Leaving AddChannel\n");
      60               3 :   rpc->result = NACL_SRPC_RESULT_OK;
      61               3 : }
      62                 : 
      63                 : void RevLog(NaClSrpcRpc* rpc,
      64                 :             NaClSrpcArg** in_args,
      65                 :             NaClSrpcArg** out_args,
      66               0 :             NaClSrpcClosure* done) {
      67                 :   nacl::ReverseService* service = reinterpret_cast<nacl::ReverseService*>(
      68               0 :       rpc->channel->server_instance_data);
      69               0 :   char* message = in_args[0]->arrays.str;
      70               0 :   NaClSrpcClosureRunner on_return(done);
      71                 : 
      72                 :   UNREFERENCED_PARAMETER(out_args);
      73                 : 
      74               0 :   if (NULL == service->reverse_interface()) {
      75               0 :     NaClLog(1, "Log RPC, no reverse_interface.  Message: %s\n", message);
      76                 :   } else {
      77               0 :     service->reverse_interface()->Log(message);
      78               0 :   }
      79               0 : }
      80                 : 
      81                 : void ModuleInitDoneRpc(NaClSrpcRpc* rpc,
      82                 :                        NaClSrpcArg** in_args,
      83                 :                        NaClSrpcArg** out_args,
      84               2 :                        NaClSrpcClosure* done) {
      85                 :   nacl::ReverseService* service = reinterpret_cast<nacl::ReverseService*>(
      86               2 :       rpc->channel->server_instance_data);
      87               2 :   NaClSrpcClosureRunner on_return(done);
      88                 : 
      89                 :   UNREFERENCED_PARAMETER(in_args);
      90                 :   UNREFERENCED_PARAMETER(out_args);
      91                 : 
      92               2 :   NaClLog(4, "Entered ModuleInitDone\n");
      93               2 :   NaClLog(4, "service: 0x%"NACL_PRIxPTR, (uintptr_t) service);
      94               2 :   if (NULL == service->reverse_interface()) {
      95               0 :     NaClLog(4, "ModuleInitDone: no reverse_interface.  Nothing to do\n");
      96                 :   } else {
      97               2 :     NaClLog(4, "ModuleInitDone: invoking StartupInitializationComplete\n");
      98               2 :     service->reverse_interface()->StartupInitializationComplete();
      99                 :   }
     100               2 :   NaClLog(4, "Leaving ModuleInitDoneRpc\n");
     101               2 :   rpc->result = NACL_SRPC_RESULT_OK;
     102               2 : }
     103                 : 
     104                 : void ModuleExitRpc(NaClSrpcRpc* rpc,
     105                 :                    NaClSrpcArg** in_args,
     106                 :                    NaClSrpcArg** out_args,
     107               2 :                    NaClSrpcClosure* done) {
     108                 :   nacl::ReverseService* service = reinterpret_cast<nacl::ReverseService*>(
     109               2 :       rpc->channel->server_instance_data);
     110               2 :   NaClSrpcClosureRunner on_return(done);
     111                 : 
     112                 :   UNREFERENCED_PARAMETER(out_args);
     113                 : 
     114               2 :   NaClLog(4, "Entered ModuleExitRpc\n");
     115               2 :   NaClLog(4, "service: 0x%"NACL_PRIxPTR, (uintptr_t) service);
     116                 : 
     117               2 :   int exit_status = in_args[0]->u.ival;
     118               2 :   NaClLog(4, "exit_status: 0x%d\n", exit_status);
     119                 : 
     120               2 :   if (NULL == service->reverse_interface()) {
     121               0 :     NaClLog(4, "ModuleExitRpc: no reverse_interface.  Nothing to do.\n");
     122                 :   } else {
     123               2 :     NaClLog(4, "ModuleExitRpc: invoking ReportExitStatus\n");
     124               2 :     service->reverse_interface()->ReportExitStatus(exit_status);
     125                 :   }
     126               2 :   NaClLog(4, "Leaving ModuleExitRpc\n");
     127               2 :   rpc->result = NACL_SRPC_RESULT_OK;
     128               2 : }
     129                 : 
     130                 : void PostMessageRpc(NaClSrpcRpc* rpc,
     131                 :                     NaClSrpcArg** in_args,
     132                 :                     NaClSrpcArg** out_args,
     133               0 :                     NaClSrpcClosure* done) {
     134                 :   nacl::ReverseService* service = reinterpret_cast<nacl::ReverseService*>(
     135               0 :       rpc->channel->server_instance_data);
     136               0 :   char* message = in_args[0]->arrays.carr;
     137               0 :   nacl_abi_size_t nbytes = in_args[0]->u.count;
     138               0 :   NaClSrpcClosureRunner on_return(done);
     139                 : 
     140               0 :   NaClLog(4, "Entered PostMessageRpc\n");
     141               0 :   if (NULL == service->reverse_interface()) {
     142                 :     NaClLog(1, "PostMessage RPC, no reverse_interface.  Message: %s\n",
     143               0 :             message);
     144                 :   } else {
     145               0 :     service->reverse_interface()->DoPostMessage(std::string(message, nbytes));
     146                 :   }
     147               0 :   out_args[0]->u.ival = (int32_t) nbytes;
     148               0 :   NaClLog(4, "Leaving PostMessageRpc\n");
     149               0 :   rpc->result = NACL_SRPC_RESULT_OK;
     150               0 : }
     151                 : 
     152                 : // Manifest name service, internal APIs.
     153                 : //
     154                 : // Manifest file lookups result in read-only file descriptors with a
     155                 : // handle.  When the descriptor is closed, the service runtime must
     156                 : // inform the plugin of this using the handle, so that the File object
     157                 : // reference can be closed (thereby allowing the browser to delete or
     158                 : // otherwise garbage collect the file).  Files, being from the
     159                 : // manifest, cannot be deleted.  The manifest is also a read-only
     160                 : // object, so no new entries can be made to it.
     161                 : //
     162                 : // Read-only proxies do not require quota support per se, since we do
     163                 : // not limit read bandwidth.  Quota support is needed for storage
     164                 : // limits, though could also be used to limit write bandwidth (prevent
     165                 : // disk output saturation, limit malicious code's ability to cause
     166                 : // disk failures, especially with flash disks with limited write
     167                 : // cycles).
     168                 : 
     169                 : // NACL_MANIFEST_LIST list::C -- enumerate all names in the manifest
     170                 : void ManifestListRpc(NaClSrpcRpc* rpc,
     171                 :                      NaClSrpcArg** in_args,
     172                 :                      NaClSrpcArg** out_args,
     173               2 :                      NaClSrpcClosure* done) {
     174                 :   nacl::ReverseService* service = reinterpret_cast<nacl::ReverseService*>(
     175               2 :       rpc->channel->server_instance_data);
     176               2 :   NaClSrpcClosureRunner on_return(done);
     177                 : 
     178                 :   UNREFERENCED_PARAMETER(in_args);
     179                 : 
     180               2 :   if (NULL == service->reverse_interface()) {
     181               0 :     NaClLog(1, "ManifestList RPC, no reverse_interface.\n");
     182               0 :     out_args[0]->u.count = 0;
     183               0 :     rpc->result = NACL_SRPC_RESULT_OK;
     184               0 :     return;
     185                 :   }
     186                 : 
     187               2 :   std::set<nacl::string> manifest_keys;
     188               2 :   if (!service->reverse_interface()->EnumerateManifestKeys(&manifest_keys)) {
     189               0 :     NaClLog(LOG_WARNING, "ManifestList RPC: EnumerateManifestKeys failed\n");
     190               0 :     out_args[0]->u.count = 0;
     191               0 :     rpc->result = NACL_SRPC_RESULT_OK;
     192                 :     return;
     193                 :   }
     194               2 :   size_t sofar = 0;
     195               2 :   size_t space = out_args[0]->u.count;
     196               2 :   char* dest = out_args[0]->arrays.carr;
     197                 :   size_t to_write;
     198                 : 
     199               4 :   for (std::set<nacl::string>::iterator it = manifest_keys.begin();
     200                 :        it != manifest_keys.end();
     201                 :        ++it) {
     202               2 :     NaClLog(3, "ManifestList RPC: appending %s\n", it->c_str());
     203                 : 
     204               2 :     if (sofar >= space) {
     205               0 :       NaClLog(3, "ManifestList RPC: buffer too small, breaking\n");
     206               0 :       break;
     207                 :     }
     208               2 :     to_write = space - sofar;
     209               2 :     if (it->size() + 1 < to_write) {
     210               2 :       to_write = it->size() + 1;
     211                 :     } else {
     212               0 :       NaClLog(3, "ManifestList RPC: truncating entry %s\n", it->c_str());
     213                 :     }
     214               2 :     strncpy(dest + sofar, it->c_str(), to_write);
     215               2 :     NaClLog(3, "ManifestList RPC: %.*s\n", (int) to_write, dest + sofar);
     216               2 :     sofar += to_write;
     217                 :   }
     218                 : 
     219               2 :   NaClLog(3, "ManifestList RPC: total size %"NACL_PRIdS"\n", sofar);
     220                 : 
     221               2 :   out_args[0]->u.count = static_cast<nacl_abi_size_t>(sofar);
     222               2 :   rpc->result = NACL_SRPC_RESULT_OK;
     223                 : }
     224                 : 
     225                 : // NACL_MANIFEST_LOOKUP lookup:si:ihC -- look up by string name,
     226                 : // resulting in a handle (if name is in the preimage), a object proxy
     227                 : // handle, and an error code.
     228                 : void ManifestLookupRpc(NaClSrpcRpc* rpc,
     229                 :                        NaClSrpcArg** in_args,
     230                 :                        NaClSrpcArg** out_args,
     231               0 :                        NaClSrpcClosure* done) {
     232               0 :   char* fname = in_args[0]->arrays.str;
     233               0 :   int flags = in_args[0]->u.ival;
     234               0 :   int32_t posix_desc = -1;
     235                 :   nacl::ReverseService* service = reinterpret_cast<nacl::ReverseService*>(
     236               0 :       rpc->channel->server_instance_data);
     237               0 :   NaClSrpcClosureRunner on_return(done);
     238                 : 
     239               0 :   NaClLog(0, "ManifestLookupRpc: %s, %d\n", fname, flags);
     240                 : 
     241               0 :   out_args[2]->u.count = 0;
     242                 :   // by default we return a failure, so no proxy handle
     243               0 :   if (NULL == service->reverse_interface()) {
     244               0 :     NaClLog(0, "ManifestLookupRpc: no reverse service, returning error\n");
     245                 :     // no reverse interface, all file open requests get -1.
     246               0 :     out_args[0]->u.ival = 0;  // ok, but failed.
     247               0 :     out_args[1]->u.hval = (struct NaClDesc*) NaClDescInvalidMake();
     248               0 :     rpc->result = NACL_SRPC_RESULT_OK;
     249                 :     return;
     250                 :   }
     251                 : 
     252               0 :   NaClLog(0, "ManifestLookupRpc: invoking OpenManifestEntry\n");
     253               0 :   if (!service->reverse_interface()->OpenManifestEntry(fname,
     254                 :                                                        &posix_desc)
     255                 :       || -1 == posix_desc) {
     256               0 :     NaClLog(0, "ManifestLookupRpc: OpenManifestEntry failed.\n");
     257               0 :     out_args[0]->u.ival = 0;  // ok, but failed.
     258               0 :     out_args[1]->u.hval = (struct NaClDesc*) NaClDescInvalidMake();
     259               0 :     rpc->result = NACL_SRPC_RESULT_OK;
     260               0 :     return;
     261                 :   }
     262                 :   NaClLog(0,
     263                 :           "ManifestLookupRpc: OpenManifestEntry returned desc %d.\n",
     264               0 :           posix_desc);
     265                 :   struct NaClHostDesc *hd = reinterpret_cast<struct NaClHostDesc*>(
     266               0 :       malloc(sizeof *hd));
     267               0 :   CHECK(hd != NULL);
     268               0 :   CHECK(NaClHostDescPosixTake(hd, posix_desc, NACL_ABI_O_RDONLY) == 0);
     269               0 :   struct NaClDescIoDesc *diod = NaClDescIoDescMake(hd);
     270               0 :   CHECK(diod != NULL);
     271               0 :   out_args[1]->u.hval = (struct NaClDesc *) diod;
     272               0 :   out_args[2]->u.count = 10;
     273               0 :   strncpy(out_args[2]->arrays.carr, "123456789", 10);
     274               0 :   rpc->result = NACL_SRPC_RESULT_OK;
     275                 : }
     276                 : 
     277                 : // NACL_MANIFEST_UNREF unref:C:i -- dereferences the file by object
     278                 : // proxy handle.  The file descriptor should have been closed on the
     279                 : // other side (it was a copy due to the sendmsg anyway).
     280                 : void ManifestUnrefRpc(NaClSrpcRpc* rpc,
     281                 :                       NaClSrpcArg** in_args,
     282                 :                       NaClSrpcArg** out_args,
     283               0 :                       NaClSrpcClosure* done) {
     284               0 :   char* proxy_handle = in_args[0]->arrays.carr;
     285               0 :   NaClSrpcClosureRunner on_return(done);
     286                 : 
     287               0 :   NaClLog(0, "ManifestUnrefRpc: %.*s\n", 10, proxy_handle);
     288                 :   // Placeholder.  This RPC will be replaced by real code that
     289                 :   // looks up the object proxy handle to close the Pepper file object.
     290                 :   //
     291                 :   // TODO(bsy): replace with real code.
     292               0 :   out_args[0]->u.ival = 0;  // ok
     293               0 :   rpc->result = NACL_SRPC_RESULT_OK;
     294               0 : }
     295                 : 
     296                 : void RequestQuotaForWriteRpc(NaClSrpcRpc* rpc,
     297                 :                              NaClSrpcArg** in_args,
     298                 :                              NaClSrpcArg** out_args,
     299               0 :                              NaClSrpcClosure* done) {
     300                 :   nacl::ReverseService* service = reinterpret_cast<nacl::ReverseService*>(
     301               0 :       rpc->channel->server_instance_data);
     302                 :   nacl::string file_id = nacl::string(in_args[0]->arrays.carr,
     303               0 :                                       in_args[0]->u.count);
     304               0 :   int64_t offset = in_args[1]->u.lval;
     305               0 :   int64_t length = in_args[2]->u.lval;
     306               0 :   int64_t quota_granted = 0;
     307               0 :   NaClSrpcClosureRunner on_return(done);
     308               0 :   NaClLog(4, "Entered RequestQuotaForWriteRpc\n");
     309               0 :   if (NULL == service->reverse_interface()) {
     310               0 :     NaClLog(1, "RequestQuotaForWrite RPC, no reverse_interface.\n");
     311                 :   } else {
     312                 :     quota_granted =
     313                 :         service->reverse_interface()->RequestQuotaForWrite(file_id,
     314                 :                                                            offset,
     315               0 :                                                            length);
     316                 :   }
     317               0 :   out_args[0]->u.lval = quota_granted;
     318               0 :   NaClLog(4, "Leaving RequestQuotaForWriteRpc\n");
     319               0 :   rpc->result = NACL_SRPC_RESULT_OK;
     320               0 : }
     321                 : 
     322                 : }  // namespace
     323                 : 
     324                 : namespace nacl {
     325                 : 
     326                 : // need NaClThreadIfFactoryFunction that keeps "this" to do counting
     327                 : 
     328                 : struct ReverseCountingThreadInterface {
     329                 :   struct NaClThreadInterface base NACL_IS_REFCOUNT_SUBCLASS;
     330                 :   nacl::ReverseService* rev;
     331                 : };
     332                 : 
     333                 : /* fwd */ extern NaClThreadInterfaceVtbl const kReverseThreadInterfaceVtbl;
     334                 : 
     335                 : int ReverseThreadIfFactoryFn(
     336                 :     void* factory_data,
     337                 :     NaClThreadIfStartFunction fn_ptr,
     338                 :     void* thread_data,
     339                 :     size_t thread_stack_size,
     340                 :     NaClThreadInterface** out_new_thread);  // fwd
     341                 : 
     342                 : int ReverseThreadIfCtor_protected(
     343                 :     ReverseCountingThreadInterface* self,
     344                 :     void* factory_data,
     345                 :     NaClThreadIfStartFunction fn_ptr,
     346                 :     void* thread_data,
     347               5 :     size_t thread_stack_size) {
     348               5 :   ReverseService* rev = reinterpret_cast<ReverseService*>(factory_data);
     349                 : 
     350               5 :   if (!NaClThreadInterfaceCtor_protected(
     351                 :           reinterpret_cast<NaClThreadInterface*>(self),
     352                 :           ReverseThreadIfFactoryFn,
     353                 :           reinterpret_cast<void*>(rev->Ref()),
     354                 :           fn_ptr,
     355                 :           thread_data,
     356                 :           thread_stack_size)) {
     357                 :     NaClLog(4,
     358                 :             ("ReverseService::ReverseThreadIfFactoryFn:"
     359               0 :              " placement base class ctor failed\n"));
     360               0 :     return 0;
     361                 :   }
     362               5 :   self->rev = rev;
     363               5 :   rev->IncrThreadCount();
     364                 :   NACL_VTBL(NaClRefCount, self) =
     365               5 :       reinterpret_cast<NaClRefCountVtbl const*>(&kReverseThreadInterfaceVtbl);
     366               5 :   return 1;
     367                 : }
     368                 : 
     369                 : /*
     370                 :  * Takes ownership of rev reference.  Caller should Ref() the argument
     371                 :  * and Unref on failure if caller does not wish to pass ownership.
     372                 :  */
     373                 : int ReverseThreadIfFactoryFn(
     374                 :     void* factory_data,
     375                 :     NaClThreadIfStartFunction fn_ptr,
     376                 :     void* thread_data,
     377                 :     size_t thread_stack_size,
     378               5 :     NaClThreadInterface** out_new_thread) {
     379               5 :   NaClLog(4, "ReverseService::ReverseThreadIfFactoryFn\n");
     380                 : 
     381               5 :   nacl::scoped_ptr_malloc<ReverseCountingThreadInterface> new_thread;
     382                 : 
     383                 :   new_thread.reset(reinterpret_cast<ReverseCountingThreadInterface*>(
     384               5 :       malloc(sizeof *new_thread.get())));
     385               5 :   if (NULL == new_thread.get()) {
     386               0 :     return 0;
     387                 :   }
     388               5 :   if (!ReverseThreadIfCtor_protected(new_thread.get(),
     389                 :                                      factory_data,
     390                 :                                      fn_ptr,
     391                 :                                      thread_data,
     392                 :                                      thread_stack_size)) {
     393               0 :     return 0;
     394                 :   }
     395                 :   *out_new_thread = reinterpret_cast<NaClThreadInterface*>(
     396               5 :       new_thread.release());
     397               5 :   return 1;
     398                 : }
     399                 : 
     400               5 : void ReverseThreadIfDtor(struct NaClRefCount* vself) {
     401                 :   ReverseCountingThreadInterface* self =
     402               5 :       (ReverseCountingThreadInterface*) vself;
     403                 : 
     404               5 :   self->rev->Unref();
     405               5 :   self->rev = NULL;
     406                 : 
     407               5 :   NACL_VTBL(NaClRefCount, self) = &kNaClRefCountVtbl;
     408               5 :   (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
     409               5 : }
     410                 : 
     411               5 : void ReverseThreadIfLaunchCallback(struct NaClThreadInterface* self) {
     412                 :   NaClLog(4,
     413                 :           ("ReverseService::ReverseThreadIfLaunchCallback: thread 0x%"
     414                 :            NACL_PRIxPTR" is launching\n"),
     415               5 :           (uintptr_t) self);
     416               5 : }
     417                 : 
     418                 : void ReverseThreadIfExit(struct NaClThreadInterface* vself,
     419               5 :                          void* exit_code) {
     420                 :   ReverseCountingThreadInterface *self =
     421               5 :       reinterpret_cast<ReverseCountingThreadInterface*>(vself);
     422                 :   NaClLog(4,
     423                 :           ("ReverseService::ReverseThreadIfExit: thread 0x%"NACL_PRIxPTR
     424                 :            " is exiting\n"),
     425               5 :           (uintptr_t) vself);
     426                 : 
     427               5 :   self->rev->DecrThreadCount();
     428                 : 
     429               5 :   NaClRefCountUnref(reinterpret_cast<struct NaClRefCount*>(self));
     430               5 :   NaClThreadExit(static_cast<int>(reinterpret_cast<uintptr_t>(exit_code)));
     431               0 : }
     432                 : 
     433                 : NaClThreadInterfaceVtbl const kReverseThreadInterfaceVtbl = {
     434                 :   {
     435                 :     ReverseThreadIfDtor,
     436                 :   },
     437                 :   NaClThreadInterfaceStartThread,
     438                 :   ReverseThreadIfLaunchCallback,
     439                 :   ReverseThreadIfExit,
     440                 : };
     441                 : 
     442                 : NaClSrpcHandlerDesc const ReverseService::handlers[] = {
     443                 :   { NACL_REVERSE_CONTROL_TEST, Test, },
     444                 :   { NACL_REVERSE_CONTROL_LOG, RevLog, },
     445                 :   { NACL_REVERSE_CONTROL_ADD_CHANNEL, AddChannel, },
     446                 :   { NACL_REVERSE_CONTROL_INIT_DONE, ModuleInitDoneRpc, },
     447                 :   { NACL_REVERSE_CONTROL_REPORT_STATUS, ModuleExitRpc, },
     448                 :   { NACL_REVERSE_CONTROL_POST_MESSAGE, PostMessageRpc, },
     449                 :   { NACL_MANIFEST_LIST, ManifestListRpc, },
     450                 :   { NACL_MANIFEST_LOOKUP, ManifestLookupRpc, },
     451                 :   { NACL_MANIFEST_UNREF, ManifestUnrefRpc, },
     452                 :   { NACL_REVERSE_REQUEST_QUOTA_FOR_WRITE, RequestQuotaForWriteRpc, },
     453                 :   { NULL, NULL, },
     454                 : };
     455                 : 
     456                 : ReverseService::ReverseService(nacl::DescWrapper* conn_cap,
     457               2 :                                ReverseInterface* rif)
     458                 :     : service_socket_(NULL),
     459                 :       reverse_interface_(rif),
     460               2 :       thread_count_(0) {
     461                 :   /*
     462                 :    * We wait for service threads to exit before dtor'ing, so the
     463                 :    * reference to this passed to the ctor for the service_socket_ for
     464                 :    * use by the thread factory will have a longer lifetime than this
     465                 :    * object.
     466                 :    */
     467               2 :   NaClLog(4, "ReverseService::ReverseService ctor invoked\n");
     468               2 :   NaClXMutexCtor(&mu_);
     469               2 :   NaClXCondVarCtor(&cv_);
     470                 :   service_socket_.reset(new ReverseSocket(conn_cap,
     471                 :                                           handlers,
     472                 :                                           ReverseThreadIfFactoryFn,
     473               2 :                                           reinterpret_cast<void*>(this)));
     474               2 : }
     475                 : 
     476               2 : ReverseService::~ReverseService() {
     477               2 :   if (thread_count_ != 0) {
     478               0 :     NaClLog(LOG_FATAL, "ReverseService dtor when thread count is nonzero\n");
     479                 :   }
     480               2 :   NaClCondVarDtor(&cv_);
     481               2 :   NaClMutexDtor(&mu_);
     482               2 : }
     483                 : 
     484                 : 
     485                 : static void RevServiceCbBinder(void *state,
     486               2 :                                int  server_loop_ret) {
     487               2 :   ReverseService *obj = reinterpret_cast<ReverseService *>(state);
     488                 : 
     489                 :   UNREFERENCED_PARAMETER(server_loop_ret);
     490               2 :   obj->reverse_interface()->ReportCrash();
     491               2 : }
     492                 : 
     493                 : 
     494               5 : bool ReverseService::Start(bool crash_report) {
     495               5 :   NaClLog(4, "Entered ReverseService::Start\n");
     496               5 :   if (crash_report) {
     497                 :     return service_socket_->StartServiceCb(RevServiceCbBinder,
     498               2 :                                            reinterpret_cast<void*>(this));
     499                 :   } else {
     500                 :     return service_socket_->StartServiceCb(NULL,
     501               3 :                                            reinterpret_cast<void*>(this));
     502                 :   }
     503                 : }
     504                 : 
     505               2 : void ReverseService::WaitForServiceThreadsToExit() {
     506               2 :   NaClLog(4, "ReverseService::WaitForServiceThreadsToExit\n");
     507               2 :   NaClXMutexLock(&mu_);
     508               6 :   while (0 != thread_count_) {
     509               2 :     NaClXCondVarWait(&cv_, &mu_);
     510               2 :     NaClLog(5, "ReverseService::WaitForServiceThreadsToExit: woke up\n");
     511                 :   }
     512               2 :   NaClXMutexUnlock(&mu_);
     513               2 :   NaClLog(4, "ReverseService::WaitForServiceThreadsToExit ALL DONE\n");
     514               2 : }
     515                 : 
     516               5 : void ReverseService::IncrThreadCount() {
     517               5 :   NaClLog(5, "ReverseService::IncrThreadCount\n");
     518               5 :   NaClXMutexLock(&mu_);
     519               5 :   if (0 == ++thread_count_) {
     520                 :     NaClLog(LOG_FATAL,
     521               0 :             "ReverseService::IncrThreadCount Thread count overflow!\n");
     522                 :   }
     523               5 :   NaClXMutexUnlock(&mu_);
     524               5 : }
     525                 : 
     526               5 : void ReverseService::DecrThreadCount() {
     527               5 :   NaClLog(5, "ReverseService::DecrThreadCount\n");
     528               5 :   NaClXMutexLock(&mu_);
     529               5 :   if (0 == thread_count_) {
     530                 :     NaClLog(LOG_FATAL,
     531                 :             ("ReverseService::DecrThreadCount:"
     532               0 :              " Decrementing thread count when count is zero\n"));
     533                 :   }
     534               5 :   if (0 == --thread_count_) {
     535               2 :     NaClXCondVarBroadcast(&cv_);
     536                 :   }
     537               5 :   NaClXMutexUnlock(&mu_);
     538               5 : }
     539                 : 
     540              24 : }  // namespace nacl

Generated by: LCOV version 1.7