LCOV - code coverage report
Current view: directory - src/trusted/simple_service - nacl_simple_service.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 182 145 79.7 %
Date: 2014-06-18 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 "native_client/src/trusted/simple_service/nacl_simple_service.h"
       8                 : 
       9                 : #include "native_client/src/include/nacl_compiler_annotations.h"
      10                 : 
      11                 : #include "native_client/src/shared/platform/nacl_check.h"
      12                 : #include "native_client/src/shared/platform/nacl_log.h"
      13                 : #include "native_client/src/shared/platform/nacl_threads.h"
      14                 : #include "native_client/src/shared/srpc/nacl_srpc.h"
      15                 : 
      16                 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
      17                 : #include "native_client/src/trusted/desc/nacl_desc_conn_cap.h"
      18                 : #include "native_client/src/trusted/desc/nrd_xfer.h"
      19                 : 
      20                 : #include "native_client/src/trusted/nacl_base/nacl_refcount.h"
      21                 : 
      22                 : #include "native_client/src/trusted/service_runtime/nacl_config.h"
      23                 : /* NACL_KERN_STACK_SIZE */
      24                 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
      25                 : 
      26                 : #include "native_client/src/trusted/threading/nacl_thread_interface.h"
      27                 : 
      28                 : int NaClSimpleServiceConnectionCtor(
      29              16 :     struct NaClSimpleServiceConnection  *self,
      30              16 :     struct NaClSimpleService            *server,
      31              16 :     struct NaClDesc                     *conn,
      32              16 :     void                                *instance_data) {
      33              16 :   NaClLog(4,
      34                 :           "NaClSimpleServiceConnectionCtor: self 0x%"NACL_PRIxPTR"\n",
      35                 :           (uintptr_t) self);
      36              16 :   if (!NaClRefCountCtor((struct NaClRefCount *) self)) {
      37               0 :     return 0;
      38                 :   }
      39              16 :   self->server = (struct NaClSimpleService *) NaClRefCountRef(
      40                 :       (struct NaClRefCount *) server);
      41              16 :   self->connected_socket = (struct NaClDesc *) NaClRefCountRef(
      42                 :       (struct NaClRefCount *) conn);
      43              16 :   self->instance_data = instance_data;
      44                 : 
      45              16 :   self->thread = NULL;
      46                 : 
      47              16 :   self->base.vtbl = (struct NaClRefCountVtbl const *)
      48                 :       &kNaClSimpleServiceConnectionVtbl;
      49              16 :   return 1;
      50              16 : }
      51                 : 
      52               3 : void NaClSimpleServiceConnectionDtor(struct NaClRefCount *vself) {
      53               3 :   struct NaClSimpleServiceConnection *self =
      54                 :       (struct NaClSimpleServiceConnection *) vself;
      55                 : 
      56               3 :   NaClRefCountUnref((struct NaClRefCount *) self->server);
      57               3 :   NaClRefCountUnref((struct NaClRefCount *) self->connected_socket);
      58                 : 
      59               3 :   NACL_VTBL(NaClRefCount, self) = &kNaClRefCountVtbl;
      60               3 :   (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
      61               3 : }
      62                 : 
      63                 : int NaClSimpleServiceConnectionServerLoop(
      64              16 :     struct NaClSimpleServiceConnection *self) {
      65              16 :   int retval;
      66                 : 
      67              16 :   NaClLog(4,
      68                 :           "NaClSimpleServiceConnectionServerLoop: handling RPC requests from"
      69                 :           " client at socket %"NACL_PRIxPTR"\n",
      70                 :           (uintptr_t) self->connected_socket);
      71              16 :   retval = NaClSrpcServerLoop(self->connected_socket,
      72                 :                               self->server->handlers,
      73                 :                               self->instance_data);
      74              16 :   NaClLog(4,
      75                 :           "NaClSimpleServiceConnectionServerLoop: NaClSrpcServerLoop exited,"
      76                 :           " value %d\n", retval);
      77              16 :   return retval;
      78                 : }
      79                 : 
      80                 : struct NaClSimpleServiceConnectionVtbl
      81                 : const kNaClSimpleServiceConnectionVtbl = {
      82                 :   {
      83                 :     NaClSimpleServiceConnectionDtor,
      84                 :   },
      85                 :   NaClSimpleServiceConnectionServerLoop,
      86                 : };
      87                 : 
      88                 : 
      89                 : /* default rpc_handler */
      90                 : void NaClSimpleServiceRpcHandler(
      91              16 :     struct NaClSimpleService           *self,
      92              16 :     struct NaClSimpleServiceConnection *conn) {
      93              32 :   UNREFERENCED_PARAMETER(self);
      94                 : 
      95              16 :   (*NACL_VTBL(NaClSimpleServiceConnection, conn)->ServerLoop)(
      96                 :       conn);
      97              16 : }
      98                 : 
      99              16 : static void *RpcHandlerBase(struct NaClThreadInterface *tif) {
     100              16 :   struct NaClSimpleServiceConnection  *conn =
     101                 :       (struct NaClSimpleServiceConnection *) tif->thread_data;
     102                 : 
     103              16 :   NaClLog(4, "Entered RpcHandlerBase, invoking RpcHandler virtual fn\n");
     104              16 :   (*NACL_VTBL(NaClSimpleService, conn->server)->RpcHandler)(conn->server,
     105                 :                                                             conn);
     106              16 :   NaClLog(4, "Leaving RpcHandlerBase\n");
     107                 :   /*
     108                 :    * The unref of conn may Dtor the currently running thread.  This is
     109                 :    * okay, since this only removes the ability to use the thread
     110                 :    * handle (in Windows) but does not otherwise affect the thread.  We
     111                 :    * don't log afterwards, just in case the logging code (is later
     112                 :    * modified to) use thread info.
     113                 :    */
     114              16 :   NaClRefCountUnref((struct NaClRefCount *) conn);
     115              16 :   return (void *) NULL;
     116                 : }
     117                 : 
     118                 : static int NaClSimpleServiceCtorIntern(
     119             563 :     struct NaClSimpleService          *self,
     120             563 :     struct NaClSrpcHandlerDesc const  *srpc_handlers,
     121             563 :     NaClThreadIfFactoryFunction       thread_factory_fn,
     122             563 :     void                              *thread_factory_data) {
     123             563 :   NaClLog(4,
     124                 :           "NaClSimpleServiceCtorIntern, self 0x%"NACL_PRIxPTR"\n",
     125                 :           (uintptr_t) self);
     126             563 :   if (!NaClRefCountCtor((struct NaClRefCount *) self)) {
     127               0 :     NaClLog(4, "NaClSimpleServiceCtorIntern: NaClRefCountCtor failed\n");
     128               0 :     return 0;
     129                 :   }
     130             563 :   self->handlers = srpc_handlers;
     131             563 :   self->thread_factory_fn = thread_factory_fn;
     132             563 :   self->thread_factory_data = thread_factory_data;
     133             563 :   self->acceptor = (struct NaClThreadInterface *) NULL;
     134                 : 
     135             563 :   self->base.vtbl = (struct NaClRefCountVtbl const *) &kNaClSimpleServiceVtbl;
     136             563 :   NaClLog(4, "Leaving NaClSimpleServiceCtorIntern\n");
     137             563 :   return 1;
     138             563 : }
     139                 : 
     140                 : int NaClSimpleServiceCtor(
     141             553 :     struct NaClSimpleService          *self,
     142             553 :     struct NaClSrpcHandlerDesc const  *srpc_handlers,
     143             553 :     NaClThreadIfFactoryFunction       thread_factory_fn,
     144             553 :     void                              *thread_factory_data) {
     145             553 :   NaClLog(4,
     146                 :           "Entered NaClSimpleServiceCtor: self 0x%"NACL_PRIxPTR"\n",
     147                 :           (uintptr_t) self);
     148                 : 
     149             553 :   if (0 != NaClCommonDescMakeBoundSock(self->bound_and_cap)) {
     150               0 :     return 0;
     151                 :   }
     152             553 :   if (!NaClSimpleServiceCtorIntern(self, srpc_handlers,
     153                 :                                    thread_factory_fn, thread_factory_data)) {
     154               0 :     NaClDescUnref(self->bound_and_cap[0]);
     155               0 :     NaClDescUnref(self->bound_and_cap[1]);
     156               0 :     return 0;
     157                 :   }
     158             553 :   return 1;
     159             553 : }
     160                 : 
     161                 : int NaClSimpleServiceWithSocketCtor(
     162              10 :     struct NaClSimpleService          *self,
     163              10 :     struct NaClSrpcHandlerDesc const  *srpc_handlers,
     164              10 :     NaClThreadIfFactoryFunction       thread_factory_fn,
     165              10 :     void                              *thread_factory_data,
     166              10 :     struct NaClDesc                   *service_port,
     167              10 :     struct NaClDesc                   *sock_addr) {
     168              10 :   NaClLog(4,
     169                 :           "NaClSimpleServiceWithSocketCtor: self 0x%"NACL_PRIxPTR"\n",
     170                 :           (uintptr_t) self);
     171              10 :   if (!NaClSimpleServiceCtorIntern(self, srpc_handlers,
     172                 :                                    thread_factory_fn, thread_factory_data)) {
     173               0 :     return 0;
     174                 :   }
     175              10 :   self->bound_and_cap[0] = NaClDescRef(service_port);
     176              10 :   self->bound_and_cap[1] = NaClDescRef(sock_addr);
     177                 : 
     178              10 :   return 1;
     179              10 : }
     180                 : 
     181               0 : void NaClSimpleServiceDtor(struct NaClRefCount *vself) {
     182               0 :   struct NaClSimpleService *self = (struct NaClSimpleService *) vself;
     183                 : 
     184               0 :   NaClRefCountSafeUnref((struct NaClRefCount *) self->bound_and_cap[0]);
     185               0 :   NaClRefCountSafeUnref((struct NaClRefCount *) self->bound_and_cap[1]);
     186                 : 
     187               0 :   NACL_VTBL(NaClRefCount, self) = &kNaClRefCountVtbl;
     188               0 :   (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
     189               0 : }
     190                 : 
     191                 : int NaClSimpleServiceConnectionFactoryWithInstanceData(
     192              15 :     struct NaClSimpleService            *self,
     193              15 :     struct NaClDesc                     *conn,
     194              15 :     void                                *instance_data,
     195              15 :     struct NaClSimpleServiceConnection  **out) {
     196              15 :   struct NaClSimpleServiceConnection  *server_conn;
     197              15 :   int                                 status;
     198                 : 
     199              15 :   NaClLog(4, "Entered NaClSimpleServiceConnectionFactory\n");
     200              15 :   server_conn = malloc(sizeof *server_conn);
     201              15 :   if (NULL == server_conn) {
     202               0 :     status = -NACL_ABI_ENOMEM;
     203               0 :     goto abort;
     204                 :   }
     205              15 :   NaClLog(4,
     206                 :           "NaClSimpleServiceConnectionFactory: self 0x%"NACL_PRIxPTR"\n",
     207                 :           (uintptr_t) self);
     208              15 :   NaClLog(4,
     209                 :           "NaClSimpleServiceConnectionFactory: conn 0x%"NACL_PRIxPTR"\n",
     210                 :           (uintptr_t) conn);
     211              15 :   NaClLog(4,
     212                 :           "NaClSimpleServiceConnectionFactory: out 0x%"NACL_PRIxPTR"\n",
     213                 :           (uintptr_t) out);
     214                 :   /*
     215                 :    * In the common/degenerate case, factory instance data becomes
     216                 :    * connection instance data.
     217                 :    */
     218              15 :   if (!NaClSimpleServiceConnectionCtor(server_conn,
     219                 :                                        self,
     220                 :                                        conn,
     221                 :                                        instance_data)) {
     222               0 :     free(server_conn);
     223               0 :     status = -NACL_ABI_EIO;
     224               0 :     goto abort;
     225                 :   }
     226              15 :   NaClLog(4,
     227                 :           "NaClSimpleServiceConnectionFactory: constructed 0x%"NACL_PRIxPTR"\n",
     228                 :           (uintptr_t) server_conn);
     229              15 :   *out = server_conn;
     230              15 :   status = 0;
     231                 :  abort:
     232              15 :   NaClLog(4, "Leaving NaClSimpleServiceConnectionFactory: status %d\n", status);
     233              15 :   return status;
     234                 : }
     235                 : 
     236                 : int NaClSimpleServiceConnectionFactory(
     237               5 :     struct NaClSimpleService            *self,
     238               5 :     struct NaClDesc                     *conn,
     239               5 :     struct NaClSimpleServiceConnection  **out) {
     240               5 :   return NaClSimpleServiceConnectionFactoryWithInstanceData(
     241                 :       self, conn, (struct NaClRefCount *) self, out);
     242                 : }
     243                 : 
     244                 : int NaClSimpleServiceAcceptConnection(
     245             538 :     struct NaClSimpleService            *self,
     246             538 :     struct NaClSimpleServiceConnection  **out) {
     247             538 :   int                                 status = -NACL_ABI_EINVAL;
     248             538 :   struct NaClSimpleServiceConnection  *conn = NULL;
     249             538 :   struct NaClDesc                     *connected_desc = NULL;
     250                 : 
     251             538 :   NaClLog(4, "Entered NaClSimpleServiceAcceptConnection\n");
     252             538 :   conn = malloc(sizeof *conn);
     253             538 :   if (NULL == conn) {
     254               0 :     return -NACL_ABI_ENOMEM;
     255                 :   }
     256                 :   /* NB: conn is allocated but not constructed */
     257              16 :   status = (*NACL_VTBL(NaClDesc, self->bound_and_cap[0])->
     258                 :             AcceptConn)(self->bound_and_cap[0], &connected_desc);
     259              16 :   if (0 != status) {
     260               0 :     NaClLog(4, "Accept failed\n");
     261               0 :     free(conn);
     262               0 :     conn = NULL;
     263               0 :     goto cleanup;
     264                 :   }
     265                 : 
     266              16 :   NaClLog(4,
     267                 :           "connected_desc is 0x%"NACL_PRIxPTR"\n",
     268                 :           (uintptr_t) connected_desc);
     269                 : 
     270              16 :   status = (*NACL_VTBL(NaClSimpleService, self)->ConnectionFactory)(
     271                 :       self,
     272                 :       connected_desc,
     273                 :       &conn);
     274              16 :   if (0 != status) {
     275               0 :     NaClLog(4, "ConnectionFactory failed\n");
     276               0 :     goto cleanup;
     277                 :   }
     278                 :   /* all okay! */
     279                 : 
     280              16 :   NaClLog(4,
     281                 :           "NaClSimpleServiceAcceptConnection: conn is 0x%"NACL_PRIxPTR"\n",
     282                 :           (uintptr_t) conn);
     283              16 :   NaClLog(4,
     284                 :           "NaClSimpleServiceAcceptConnection: out  is 0x%"NACL_PRIxPTR"\n",
     285                 :           (uintptr_t) out);
     286              16 :   *out = conn;
     287              16 :   status = 0;
     288                 : cleanup:
     289              16 :   NaClRefCountSafeUnref((struct NaClRefCount *) connected_desc);
     290              16 :   NaClLog(4, "Leaving NaClSimpleServiceAcceptConnection, status %d\n", status);
     291              16 :   return status;
     292              16 : }
     293                 : 
     294                 : int NaClSimpleServiceAcceptAndSpawnHandler(
     295              16 :     struct NaClSimpleService *self) {
     296              16 :   struct NaClSimpleServiceConnection  *conn = NULL;
     297              16 :   int                                 status;
     298                 : 
     299              16 :   NaClLog(4, "Entered NaClSimpleServiceAcceptAndSpawnHandler\n");
     300              16 :   NaClLog(4,
     301                 :           ("NaClSimpleServiceAcceptAndSpawnHandler:"
     302                 :            " &conn is 0x%"NACL_PRIxPTR"\n"),
     303                 :           (uintptr_t) &conn);
     304              16 :   status = (*NACL_VTBL(NaClSimpleService, self)->AcceptConnection)(
     305                 :       self,
     306                 :       &conn);
     307              16 :   NaClLog(4, "AcceptConnection vfn returned %d\n", status);
     308              16 :   if (0 != status) {
     309               0 :     goto abort;
     310                 :   }
     311              16 :   NaClLog(4,
     312                 :           "NaClSimpleServiceAcceptAndSpawnHandler: conn is 0x%"NACL_PRIxPTR"\n",
     313                 :           (uintptr_t) conn);
     314              16 :   NaClLog(4, "NaClSimpleServiceAcceptAndSpawnHandler: spawning thread\n");
     315                 : 
     316              48 :   CHECK(NULL == conn->thread);
     317                 : 
     318                 :   /* ownership of |conn| reference is passed to the thread */
     319              16 :   if (!NaClThreadInterfaceConstructAndStartThread(
     320                 :           self->thread_factory_fn,
     321                 :           self->thread_factory_data,
     322                 :           RpcHandlerBase,
     323                 :           conn,
     324                 :           NACL_KERN_STACK_SIZE,
     325                 :           &conn->thread)) {
     326               0 :     NaClLog(4, "NaClSimpleServiceAcceptAndSpawnHandler: no thread\n");
     327               0 :     NaClRefCountUnref((struct NaClRefCount *) conn);
     328               0 :     status = -NACL_ABI_EAGAIN;
     329               0 :     goto abort;
     330                 :   }
     331              16 :   status = 0;
     332                 : abort:
     333              16 :   NaClLog(4,
     334                 :           "Leaving NaClSimpleServiceAcceptAndSpawnHandler, status %d\n",
     335                 :           status);
     336              16 :   return status;
     337                 : }
     338                 : 
     339                 : struct NaClSimpleServiceVtbl const kNaClSimpleServiceVtbl = {
     340                 :   {
     341                 :     NaClSimpleServiceDtor,
     342                 :   },
     343                 :   NaClSimpleServiceConnectionFactory,
     344                 :   NaClSimpleServiceAcceptConnection,
     345                 :   NaClSimpleServiceAcceptAndSpawnHandler,
     346                 :   NaClSimpleServiceRpcHandler,
     347                 : };
     348                 : 
     349                 : 
     350             523 : static void *AcceptThread(struct NaClThreadInterface *tif) {
     351             523 :   struct NaClSimpleService *server =
     352                 :       (struct NaClSimpleService *) tif->thread_data;
     353                 : 
     354             523 :   NaClLog(4, "Entered AcceptThread\n");
     355             539 :   while (0 == (*NACL_VTBL(NaClSimpleService, server)->
     356                 :                AcceptAndSpawnHandler)(server)) {
     357              16 :     NaClLog(4, "AcceptThread: accepted, looping to next thread\n");
     358              16 :     continue;
     359                 :   }
     360               0 :   NaClRefCountUnref(&server->base);
     361               0 :   return (void *) NULL;
     362                 : }
     363                 : 
     364             523 : int NaClSimpleServiceStartServiceThread(struct NaClSimpleService *server) {
     365             523 :   NaClLog(4, "NaClSimpleServiceStartServiceThread: spawning thread\n");
     366            1569 :   CHECK(server->acceptor == NULL);
     367                 : 
     368            1046 :   if (!NaClThreadInterfaceConstructAndStartThread(
     369                 :           server->thread_factory_fn,
     370                 :           server->thread_factory_data,
     371                 :           AcceptThread,
     372             523 :           NaClRefCountRef(&server->base),
     373                 :           NACL_KERN_STACK_SIZE,
     374                 :           &server->acceptor)) {
     375               0 :     NaClLog(4, "NaClSimpleServiceStartServiceThread: no thread\n");
     376               0 :     NaClRefCountUnref(&server->base);  /* undo ref in Ctor call arglist */
     377               0 :     return 0;
     378                 :   }
     379             523 :   NaClLog(4, "NaClSimpleServiceStartServiceThread: success\n");
     380             523 :   return 1;
     381             523 : }

Generated by: LCOV version 1.7