LCOV - code coverage report
Current view: directory - src/trusted/simple_service - nacl_simple_rservice.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 163 124 76.1 %
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_rservice.h"
       8                 : 
       9                 : #include "native_client/src/include/nacl_compiler_annotations.h"
      10                 : #include "native_client/src/shared/platform/nacl_log.h"
      11                 : #include "native_client/src/shared/platform/nacl_threads.h"
      12                 : #include "native_client/src/shared/srpc/nacl_srpc.h"
      13                 : 
      14                 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
      15                 : #include "native_client/src/trusted/desc/nacl_desc_conn_cap.h"
      16                 : #include "native_client/src/trusted/desc/nrd_xfer.h"
      17                 : 
      18                 : #include "native_client/src/trusted/nacl_base/nacl_refcount.h"
      19                 : 
      20                 : #include "native_client/src/trusted/service_runtime/nacl_config.h"
      21                 : /* NACL_KERN_STACK_SIZE */
      22                 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
      23                 : 
      24                 : int NaClSimpleRevClientCtor(
      25               3 :     struct NaClSimpleRevClient  *self,
      26               3 :     void                        (*callback)(
      27                 :         void                        *state,
      28                 :         struct NaClThreadInterface  *tif,
      29                 :         struct NaClDesc             *conn),
      30               3 :     void                        *state,
      31               3 :     NaClThreadIfFactoryFunction thread_factory_fn,
      32               3 :     void                        *thread_factory_data) {
      33               3 :   NaClLog(4,
      34                 :           "NaClSimpleRevClientCtor: this 0x%"NACL_PRIxPTR"\n",
      35                 :           (uintptr_t) self);
      36               3 :   if (!NaClRefCountCtor(&self->base)) {
      37               0 :     NaClLog(4, "NaClSimpleRevClientCtor: NaClRefCountCtor failed\n");
      38               0 :     goto done;
      39                 :   }
      40               3 :   if (0 != NaClCommonDescMakeBoundSock(self->bound_and_cap)) {
      41               0 :     goto bound_failed;
      42                 :   }
      43                 : 
      44               3 :   self->acceptor = (struct NaClThreadInterface *) NULL;
      45               3 :   self->client_callback = callback;
      46               3 :   self->state = state;
      47               3 :   self->thread_factory_fn = thread_factory_fn;
      48               3 :   self->thread_factory_data = thread_factory_data;
      49               3 :   NaClLog(4,
      50                 :           ("NaClSimpleRevClientCtor: callback 0x%"NACL_PRIxPTR
      51                 :            ", state 0x%"NACL_PRIxPTR"\n"),
      52                 :           (uintptr_t) callback,
      53                 :           (uintptr_t) state);
      54               3 :   NACL_VTBL(NaClRefCount, self) =
      55                 :       (struct NaClRefCountVtbl *) &kNaClSimpleRevClientVtbl;
      56               3 :   return 1;
      57                 : 
      58                 : bound_failed:
      59               0 :   (*NACL_VTBL(NaClRefCount, self)->Dtor)(&self->base);
      60                 : done:
      61               0 :   return 0;
      62               3 : }
      63                 : 
      64               0 : static void NaClSimpleRevClientDtor(struct NaClRefCount *vself) {
      65               0 :   struct NaClSimpleRevClient *self =
      66                 :       (struct NaClSimpleRevClient *) vself;
      67                 : 
      68               0 :   NaClDescUnref(self->bound_and_cap[0]);
      69               0 :   NaClDescUnref(self->bound_and_cap[1]);
      70                 : 
      71               0 :   NACL_VTBL(NaClRefCount, self) = &kNaClRefCountVtbl;
      72               0 :   (*NACL_VTBL(NaClRefCount, self)->Dtor)(&self->base);
      73               0 : }
      74                 : 
      75                 : struct NaClSimpleRevClientVtbl const kNaClSimpleRevClientVtbl = {
      76                 :   {
      77                 :     NaClSimpleRevClientDtor,
      78                 :   },
      79                 : };
      80                 : 
      81               3 : static void *RevRpcHandlerBase(struct NaClThreadInterface *tif) {
      82               3 :   struct NaClSimpleRevClient *self =
      83                 :       (struct NaClSimpleRevClient *) tif->thread_data;
      84                 : 
      85               3 :   int             status;
      86               3 :   struct NaClDesc *conn;
      87                 : 
      88               3 :   NaClLog(4, "Entered RevRpcHandlerBase\n");
      89               3 :   while (0 == (status =
      90               4 :                (*NACL_VTBL(NaClDesc, self->bound_and_cap[0])->AcceptConn)(
      91                 :                    self->bound_and_cap[0], &conn))) {
      92               4 :     NaClLog(4,
      93                 :             ("RevRpcHandlerBase: Accept returned success,"
      94                 :              " invoking callback"
      95                 :              " 0x%"NACL_PRIxPTR"(0x%"NACL_PRIxPTR",0x%"NACL_PRIxPTR")\n"),
      96                 :             (uintptr_t) self->client_callback,
      97                 :             (uintptr_t) self->state,
      98                 :             (uintptr_t) conn);
      99                 :     /*
     100                 :      * The callback should not block; if needed, it should spawn
     101                 :      * another thread.  The callback takes ownership of |conn| -- it
     102                 :      * may Unref |conn| prior to returning or the ownership of |conn|
     103                 :      * may be passed to another thread (e.g., newly spawned, or waking
     104                 :      * up and giving |conn| to the thread that made the connection
     105                 :      * request in the first place).
     106                 :      */
     107               4 :     (*self->client_callback)(self->state, tif, conn);
     108               4 :     NaClLog(4,
     109                 :             "RevRpcHandlerBase: callback finished.\n");
     110               4 :   }
     111               0 :   NaClLog(LOG_INFO,
     112                 :           ("NaClSimpleRevClient::RevRpcHandlerBase:"
     113                 :            " AcceptConn failed, status %d\n"),
     114                 :           status);
     115                 :   /*
     116                 :    * The unref of self may Dtor the currently running thread.  This is
     117                 :    * okay, since this only removes the ability to use the thread
     118                 :    * handle (in Windows) but does not otherwise affect the thread.  We
     119                 :    * don't log afterwards, just in case the logging code (is later
     120                 :    * modified to) use thread info.
     121                 :    */
     122               0 :   NaClRefCountUnref((struct NaClRefCount *) self);
     123               0 :   return (void *) NULL;
     124                 : }
     125                 : 
     126               3 : int NaClSimpleRevClientStartServiceThread(struct NaClSimpleRevClient *self) {
     127               3 :   NaClLog(4, "Entered NaClSimpleRevClientStartServiceThread\n");
     128               3 :   if (NULL != self->acceptor) {
     129               0 :     NaClLog(LOG_FATAL,
     130                 :             "NaClSimpleRevClientStartServiceThread: dup - already started\n");
     131               0 :   }
     132               6 :   if (!NaClThreadInterfaceConstructAndStartThread(
     133                 :           self->thread_factory_fn,
     134                 :           self->thread_factory_data,
     135                 :           RevRpcHandlerBase,
     136               3 :           NaClRefCountRef((struct NaClRefCount *) self),
     137                 :           NACL_KERN_STACK_SIZE,
     138                 :           &self->acceptor)) {
     139               0 :     NaClLog(4, "NaClSimpleRevClientStartServiceThread: no thread\n");
     140               0 :     NaClRefCountUnref((struct NaClRefCount *) self);
     141               0 :     return 0;
     142                 :   }
     143               3 :   return 1;
     144               3 : }
     145                 : 
     146                 : int NaClSimpleRevServiceCtor(
     147               5 :     struct NaClSimpleRevService       *self,
     148               5 :     struct NaClDesc                   *conn_cap,
     149               5 :     struct NaClSrpcHandlerDesc const  *handlers,
     150               5 :     NaClThreadIfFactoryFunction       thread_factory_fn,
     151               5 :     void                              *thread_factory_data) {
     152               5 :   NaClLog(4,
     153                 :           "NaClSimpleRevServiceCtor: this 0x%"NACL_PRIxPTR"\n",
     154                 :           (uintptr_t) self);
     155               5 :   if (!NaClRefCountCtor(&self->base)) {
     156               0 :     NaClLog(4, "NaClSimpleRevServiceCtor: NaClRefCountCtor failed\n");
     157               0 :     return 0;
     158                 :   }
     159               5 :   self->conn_cap = conn_cap;  /* take ownership, if ctor succeeds */
     160               5 :   self->handlers = handlers;
     161                 :   /* caller ensures lifetime of handlers is at least that of self */
     162               5 :   self->thread_factory_fn = thread_factory_fn;
     163               5 :   self->thread_factory_data = thread_factory_data;
     164                 : 
     165               5 :   NACL_VTBL(NaClRefCount, self) =
     166                 :      (struct NaClRefCountVtbl *) &kNaClSimpleRevServiceVtbl;
     167                 : 
     168               5 :   NaClLog(4, "Leaving NaClSimpleRevServiceCtor\n");
     169               5 :   return 1;
     170               5 : }
     171                 : 
     172               5 : void NaClSimpleRevServiceDtor(struct NaClRefCount *vself) {
     173               5 :   struct NaClSimpleRevService *self =
     174                 :       (struct NaClSimpleRevService *) vself;
     175                 : 
     176               5 :   NaClDescUnref(self->conn_cap);
     177               5 :   self->conn_cap = NULL;
     178               5 :   self->handlers = NULL;
     179                 : 
     180               5 :   NACL_VTBL(NaClRefCount, self) = &kNaClRefCountVtbl;
     181               5 :   (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
     182               5 : }
     183                 : 
     184               8 : static void *ConnRpcBase(struct NaClThreadInterface *tif) {
     185               8 :   struct NaClSimpleRevConnection *rev_conn =
     186                 :       (struct NaClSimpleRevConnection *) tif->thread_data;
     187                 : 
     188               8 :   NaClLog(4, "Entered ConnRpcBase, invoking RpcHandler vfn\n");
     189               8 :   (*NACL_VTBL(NaClSimpleRevService, rev_conn->service)->RpcHandler)(
     190                 :       rev_conn->service, rev_conn);
     191               8 :   NaClLog(4, "Leaving ConnRpcBase\n");
     192               8 :   NaClRefCountUnref((struct NaClRefCount *) rev_conn);
     193               8 :   return (void *) NULL;
     194                 : }
     195                 : 
     196                 : int NaClSimpleRevServiceConnectAndSpawnHandlerCb(
     197               8 :     struct NaClSimpleRevService *self,
     198               8 :     void                        (*exit_cb)(void *instance_data,
     199                 :                                            int  server_loop_ret),
     200               8 :     void                        *instance_data) {
     201               8 :   int                             status;
     202               8 :   struct NaClDesc                 *conn = NULL;
     203               8 :   struct NaClSimpleRevConnection  *rev_conn;
     204                 : 
     205               8 :   NaClLog(4, "Entered NaClSimpleRevServiceConnectAndSpawnHandler\n");
     206                 :   if (0 != (status =
     207               8 :             (*NACL_VTBL(NaClDesc, self->conn_cap)->ConnectAddr)(
     208                 :                 self->conn_cap, &conn))) {
     209                 :     /* failed */
     210               0 :     NaClLog(3, "NaClSimpleRevServiceConnectAndSpawnHandler: connect failed\n");
     211               0 :     return status;
     212                 :   }
     213                 :   if (0 != (status =
     214               8 :             (*NACL_VTBL(NaClSimpleRevService, self)->RevConnectionFactory)(
     215                 :                 self, conn, exit_cb, instance_data, &rev_conn))) {
     216               0 :     NaClDescUnref(conn);
     217               0 :     NaClLog(3,
     218                 :             ("NaClSimpleRevServiceConnectAndSpawnHandler: factory failed,"
     219                 :              " error %d\n"),
     220                 :             status);
     221               0 :     return status;
     222                 :   }
     223               8 :   conn = NULL;  /* rev_conn owns the ref in conn now */
     224                 :   /*
     225                 :    * Spawn thread to use the NaClSimpleRevConnection.
     226                 :    */
     227                 :   /* rev_conn not visible to other threads, ownership passed to thread */
     228               8 :   if (!NaClThreadInterfaceConstructAndStartThread(
     229                 :           self->thread_factory_fn,
     230                 :           self->thread_factory_data,
     231                 :           ConnRpcBase,
     232                 :           (void *) rev_conn,
     233                 :           NACL_KERN_STACK_SIZE,
     234                 :           &rev_conn->thread)) {
     235                 :     /*
     236                 :      * no thread, clean up
     237                 :      */
     238               0 :     NaClLog(3, "NaClSimpleRevServiceConnectAndSpawnHandler: no thread\n");
     239               0 :     NaClRefCountUnref((struct NaClRefCount *) rev_conn);
     240               0 :     return -NACL_ABI_EAGAIN;
     241                 :   }
     242                 :   /* thread owns rev_conn */
     243               8 :   NaClLog(4, "Leaving NaClSimpleRevServiceConnectAndSpawnHandler\n");
     244               8 :   return 0;
     245               8 : }
     246                 : 
     247                 : int NaClSimpleRevServiceConnectAndSpawnHandler(
     248               0 :     struct NaClSimpleRevService *self,
     249               0 :     void                        *instance_data) {
     250               0 :   return NaClSimpleRevServiceConnectAndSpawnHandlerCb(
     251                 :       self, NULL, instance_data);
     252                 : }
     253                 : 
     254                 : int NaClSimpleRevServiceConnectionFactory(
     255               8 :     struct NaClSimpleRevService     *self,
     256               8 :     struct NaClDesc                 *conn,
     257               8 :     void                            (*exit_cb)(void *instance_data,
     258                 :                                                int  server_loop_ret),
     259               8 :     void                            *instance_data,
     260               8 :     struct NaClSimpleRevConnection  **out) {
     261               8 :   struct NaClSimpleRevConnection *rconn;
     262                 : 
     263               8 :   rconn = (struct NaClSimpleRevConnection *) malloc(sizeof *rconn);
     264               8 :   if (NULL == rconn) {
     265               0 :     NaClLog(4, "NaClSimpleRevServiceConnectionFactory:"
     266                 :             " no memory\n");
     267               0 :     return -NACL_ABI_EAGAIN;
     268                 :   }
     269                 :   /*
     270                 :    * In the common/degenerate case, factory instance_data becomes
     271                 :    * connection instance data.
     272                 :    */
     273               8 :   if (!NaClSimpleRevConnectionCtor(rconn, self, conn,
     274                 :                                    exit_cb, instance_data)) {
     275               0 :     NaClLog(4, "NaClSimpleRevServiceConnectionFactory:"
     276                 :             " NaClSimpleRevConnectionCtor failed\n");
     277               0 :     free(rconn);
     278               0 :     return -NACL_ABI_EINVAL;
     279                 :   }
     280                 : 
     281               8 :   *out = rconn;
     282               8 :   return 0;
     283               8 : }
     284                 : 
     285                 : void NaClSimpleRevServiceRpcHandler(
     286               8 :     struct NaClSimpleRevService     *self,
     287               8 :     struct NaClSimpleRevConnection  *conn) {
     288               8 :   int retval;
     289                 : 
     290               8 :   NaClLog(4, "Entered NaClSimpleRevServiceRpcHandler: ServerLoop!\n");
     291               8 :   retval = NaClSrpcServerLoop(conn->connected_socket,
     292                 :                               self->handlers,
     293                 :                               conn->instance_data);
     294               8 :   NaClLog(4,
     295                 :           "NaClSimpleRevServiceRpcHandler: NaClSrpcServerLoop returned %d\n",
     296                 :           retval);
     297               8 :   if (NULL != conn->exit_cb) {
     298               5 :     (*conn->exit_cb)(conn->instance_data, retval);
     299               5 :   }
     300               8 :   NaClLog(4, "Leaving NaClSimpleRevServiceRpcHandler\n");
     301               8 : }
     302                 : 
     303                 : struct NaClSimpleRevServiceVtbl const kNaClSimpleRevServiceVtbl = {
     304                 :   {
     305                 :     NaClSimpleRevServiceDtor,
     306                 :   },
     307                 :   NaClSimpleRevServiceConnectAndSpawnHandler,
     308                 :   NaClSimpleRevServiceConnectAndSpawnHandlerCb,
     309                 :   NaClSimpleRevServiceConnectionFactory,
     310                 :   NaClSimpleRevServiceRpcHandler,
     311                 : };
     312                 : 
     313                 : int NaClSimpleRevConnectionCtor(
     314               8 :     struct NaClSimpleRevConnection  *self,
     315               8 :     struct NaClSimpleRevService     *service,
     316               8 :     struct NaClDesc                 *conn,
     317               8 :     void                            (*exit_cb)(void *instance_data,
     318                 :                                                int  server_loop_ret),
     319               8 :     void                            *instance_data) {
     320               8 :   NaClLog(4,
     321                 :           "NaClSimpleRevConnectionCtor: this 0x%"NACL_PRIxPTR"\n",
     322                 :           (uintptr_t) self);
     323               8 :   if (!NaClRefCountCtor(&self->base)) {
     324               0 :     return 0;
     325                 :   }
     326                 : 
     327               8 :   NaClRefCountRef((struct NaClRefCount *) service);
     328               8 :   self->service = service;
     329               8 :   self->connected_socket = conn;
     330               8 :   self->exit_cb = exit_cb;
     331               8 :   self->instance_data = instance_data;
     332                 : 
     333               8 :   NACL_VTBL(NaClRefCount, self) =
     334                 :       (struct NaClRefCountVtbl *) &kNaClSimpleRevConnectionVtbl;
     335               8 :   return 1;
     336               8 : }
     337                 : 
     338               8 : void NaClSimpleRevConnectionDtor(struct NaClRefCount *vself) {
     339               8 :   struct NaClSimpleRevConnection *self =
     340                 :       (struct NaClSimpleRevConnection *) vself;
     341                 : 
     342               8 :   NaClRefCountUnref((struct NaClRefCount *) self->service);
     343               8 :   NaClRefCountUnref((struct NaClRefCount *) self->connected_socket);
     344                 : 
     345               8 :   NACL_VTBL(NaClRefCount, self) = &kNaClRefCountVtbl;
     346               8 :   (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
     347               8 : }
     348                 : 
     349                 : struct NaClRefCountVtbl kNaClSimpleRevConnectionVtbl = {
     350                 :   NaClSimpleRevConnectionDtor,
     351                 : };

Generated by: LCOV version 1.7