LCOV - code coverage report
Current view: directory - src/trusted/simple_service - nacl_simple_rservice.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 128 56 43.8 %
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 "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                 :     struct NaClSimpleRevClient  *self,
      26                 :     void                        (*callback)(
      27                 :         void                        *state,
      28                 :         struct NaClThreadInterface  *tif,
      29                 :         struct NaClDesc             *conn),
      30                 :     void                        *state,
      31                 :     NaClThreadIfFactoryFunction thread_factory_fn,
      32               0 :     void                        *thread_factory_data) {
      33               0 :   NaClLog(4,
      34                 :           "NaClSimpleRevClientCtor: this 0x%"NACL_PRIxPTR"\n",
      35                 :           (uintptr_t) self);
      36               0 :   if (!NaClRefCountCtor(&self->base)) {
      37               0 :     NaClLog(4, "NaClSimpleRevClientCtor: NaClRefCountCtor failed\n");
      38               0 :     goto done;
      39                 :   }
      40               0 :   if (0 != NaClCommonDescMakeBoundSock(self->bound_and_cap)) {
      41               0 :     goto bound_failed;
      42                 :   }
      43                 : 
      44               0 :   self->acceptor = (struct NaClThreadInterface *) NULL;
      45               0 :   self->client_callback = callback;
      46               0 :   self->state = state;
      47               0 :   self->thread_factory_fn = thread_factory_fn;
      48               0 :   self->thread_factory_data = thread_factory_data;
      49               0 :   NaClLog(4,
      50                 :           ("NaClSimpleRevClientCtor: callback 0x%"NACL_PRIxPTR
      51                 :            ", state 0x%"NACL_PRIxPTR"\n"),
      52                 :           (uintptr_t) callback,
      53                 :           (uintptr_t) state);
      54               0 :   NACL_VTBL(NaClRefCount, self) =
      55                 :       (struct NaClRefCountVtbl *) &kNaClSimpleRevClientVtbl;
      56               0 :   return 1;
      57                 : 
      58               0 : bound_failed:
      59               0 :   (*NACL_VTBL(NaClRefCount, self)->Dtor)(&self->base);
      60               0 : done:
      61               0 :   return 0;
      62                 : }
      63                 : 
      64               0 : static void NaClSimpleRevClientDtor(struct NaClRefCount *vself) {
      65                 :   struct NaClSimpleRevClient *self =
      66               0 :       (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               0 : static void *RevRpcHandlerBase(struct NaClThreadInterface *tif) {
      82                 :   struct NaClSimpleRevClient *self =
      83               0 :       (struct NaClSimpleRevClient *) tif->thread_data;
      84                 : 
      85                 :   int             status;
      86                 :   struct NaClDesc *conn;
      87                 : 
      88               0 :   NaClLog(4, "Entered RevRpcHandlerBase\n");
      89               0 :   while (0 == (status =
      90                 :                (*NACL_VTBL(NaClDesc, self->bound_and_cap[0])->AcceptConn)(
      91                 :                    self->bound_and_cap[0], &conn))) {
      92               0 :     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               0 :     (*self->client_callback)(self->state, tif, conn);
     108               0 :     NaClLog(4,
     109                 :             "RevRpcHandlerBase: callback finished.\n");
     110                 :   }
     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               0 : int NaClSimpleRevClientStartServiceThread(struct NaClSimpleRevClient *self) {
     127               0 :   NaClLog(4, "Entered NaClSimpleRevClientStartServiceThread\n");
     128               0 :   if (NULL != self->acceptor) {
     129               0 :     NaClLog(LOG_FATAL,
     130                 :             "NaClSimpleRevClientStartServiceThread: dup - already started\n");
     131                 :   }
     132               0 :   if (!NaClThreadInterfaceConstructAndStartThread(
     133                 :           self->thread_factory_fn,
     134                 :           self->thread_factory_data,
     135                 :           RevRpcHandlerBase,
     136                 :           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 :     self->acceptor = NULL;
     142               0 :     return 0;
     143                 :   }
     144               0 :   return 1;
     145                 : }
     146                 : 
     147                 : int NaClSimpleRevServiceCtor(
     148                 :     struct NaClSimpleRevService       *self,
     149                 :     struct NaClDesc                   *conn_cap,
     150                 :     struct NaClSrpcHandlerDesc const  *handlers,
     151                 :     NaClThreadIfFactoryFunction       thread_factory_fn,
     152               5 :     void                              *thread_factory_data) {
     153               5 :   NaClLog(4,
     154                 :           "NaClSimpleRevServiceCtor: this 0x%"NACL_PRIxPTR"\n",
     155                 :           (uintptr_t) self);
     156               5 :   if (!NaClRefCountCtor(&self->base)) {
     157               0 :     NaClLog(4, "NaClSimpleRevServiceCtor: NaClRefCountCtor failed\n");
     158               0 :     return 0;
     159                 :   }
     160               5 :   self->conn_cap = conn_cap;  /* take ownership, if ctor succeeds */
     161               5 :   self->handlers = handlers;
     162                 :   /* caller ensures lifetime of handlers is at least that of self */
     163               5 :   self->thread_factory_fn = thread_factory_fn;
     164               5 :   self->thread_factory_data = thread_factory_data;
     165                 : 
     166               5 :   NACL_VTBL(NaClRefCount, self) =
     167                 :      (struct NaClRefCountVtbl *) &kNaClSimpleRevServiceVtbl;
     168                 : 
     169               5 :   NaClLog(4, "Leaving NaClSimpleRevServiceCtor\n");
     170               5 :   return 1;
     171                 : }
     172                 : 
     173               2 : void NaClSimpleRevServiceDtor(struct NaClRefCount *vself) {
     174                 :   struct NaClSimpleRevService *self =
     175               2 :       (struct NaClSimpleRevService *) vself;
     176                 : 
     177               2 :   NaClDescUnref(self->conn_cap);
     178               2 :   self->conn_cap = NULL;
     179               2 :   self->handlers = NULL;
     180                 : 
     181               2 :   NACL_VTBL(NaClRefCount, self) = &kNaClRefCountVtbl;
     182               2 :   (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
     183               2 : }
     184                 : 
     185               5 : static void *ConnRpcBase(struct NaClThreadInterface *tif) {
     186                 :   struct NaClSimpleRevConnection *rev_conn =
     187               5 :       (struct NaClSimpleRevConnection *) tif->thread_data;
     188                 : 
     189               5 :   NaClLog(4, "Entered ConnRpcBase, invoking RpcHandler vfn\n");
     190               5 :   (*NACL_VTBL(NaClSimpleRevService, rev_conn->service)->RpcHandler)(
     191                 :       rev_conn->service, rev_conn);
     192               5 :   NaClLog(4, "Leaving ConnRpcBase\n");
     193               5 :   NaClRefCountUnref((struct NaClRefCount *) rev_conn);
     194               5 :   return (void *) NULL;
     195                 : }
     196                 : 
     197                 : int NaClSimpleRevServiceConnectAndSpawnHandlerCb(
     198                 :     struct NaClSimpleRevService *self,
     199                 :     void                        (*exit_cb)(void *instance_data,
     200                 :                                            int  server_loop_ret),
     201               5 :     void                        *instance_data) {
     202                 :   int                             status;
     203               5 :   struct NaClDesc                 *conn = NULL;
     204                 :   struct NaClSimpleRevConnection  *rev_conn;
     205                 : 
     206               5 :   NaClLog(4, "Entered NaClSimpleRevServiceConnectAndSpawnHandler\n");
     207               5 :   if (0 != (status =
     208                 :             (*NACL_VTBL(NaClDesc, self->conn_cap)->ConnectAddr)(
     209                 :                 self->conn_cap, &conn))) {
     210                 :     /* failed */
     211               0 :     NaClLog(3, "NaClSimpleRevServiceConnectAndSpawnHandler: connect failed\n");
     212               0 :     return status;
     213                 :   }
     214               5 :   if (0 != (status =
     215                 :             (*NACL_VTBL(NaClSimpleRevService, self)->RevConnectionFactory)(
     216                 :                 self, conn, exit_cb, instance_data, &rev_conn))) {
     217               0 :     NaClDescUnref(conn);
     218               0 :     NaClLog(3,
     219                 :             ("NaClSimpleRevServiceConnectAndSpawnHandler: factory failed,"
     220                 :              " error %d\n"),
     221                 :             status);
     222               0 :     return status;
     223                 :   }
     224               5 :   conn = NULL;  /* rev_conn owns the ref in conn now */
     225                 :   /*
     226                 :    * Spawn thread to use the NaClSimpleRevConnection.
     227                 :    */
     228                 :   /* rev_conn not visible to other threads, ownership passed to thread */
     229               5 :   if (!NaClThreadInterfaceConstructAndStartThread(
     230                 :           self->thread_factory_fn,
     231                 :           self->thread_factory_data,
     232                 :           ConnRpcBase,
     233                 :           (void *) rev_conn,
     234                 :           NACL_KERN_STACK_SIZE,
     235                 :           &rev_conn->thread)) {
     236                 :     /*
     237                 :      * no thread, clean up
     238                 :      */
     239               0 :     NaClLog(3, "NaClSimpleRevServiceConnectAndSpawnHandler: no thread\n");
     240               0 :     NaClRefCountUnref((struct NaClRefCount *) rev_conn);
     241               0 :     rev_conn->thread = NULL;
     242               0 :     return -NACL_ABI_EAGAIN;
     243                 :   }
     244                 :   /* thread owns rev_conn */
     245               5 :   NaClLog(4, "Leaving NaClSimpleRevServiceConnectAndSpawnHandler\n");
     246               5 :   return 0;
     247                 : }
     248                 : 
     249                 : int NaClSimpleRevServiceConnectAndSpawnHandler(
     250                 :     struct NaClSimpleRevService *self,
     251               0 :     void                        *instance_data) {
     252               0 :   return NaClSimpleRevServiceConnectAndSpawnHandlerCb(
     253                 :       self, NULL, instance_data);
     254                 : }
     255                 : 
     256                 : int NaClSimpleRevServiceConnectionFactory(
     257                 :     struct NaClSimpleRevService     *self,
     258                 :     struct NaClDesc                 *conn,
     259                 :     void                            (*exit_cb)(void *instance_data,
     260                 :                                                int  server_loop_ret),
     261                 :     void                            *instance_data,
     262               5 :     struct NaClSimpleRevConnection  **out) {
     263                 :   struct NaClSimpleRevConnection *rconn;
     264                 : 
     265               5 :   rconn = (struct NaClSimpleRevConnection *) malloc(sizeof *rconn);
     266               5 :   if (NULL == rconn) {
     267               0 :     NaClLog(4, "NaClSimpleRevServiceConnectionFactory:"
     268                 :             " no memory\n");
     269               0 :     return -NACL_ABI_EAGAIN;
     270                 :   }
     271                 :   /*
     272                 :    * In the common/degenerate case, factory instance_data becomes
     273                 :    * connection instance data.
     274                 :    */
     275               5 :   if (!NaClSimpleRevConnectionCtor(rconn, self, conn,
     276                 :                                    exit_cb, instance_data)) {
     277               0 :     NaClLog(4, "NaClSimpleRevServiceConnectionFactory:"
     278                 :             " NaClSimpleRevConnectionCtor failed\n");
     279               0 :     free(rconn);
     280               0 :     return -NACL_ABI_EINVAL;
     281                 :   }
     282                 : 
     283               5 :   *out = rconn;
     284               5 :   return 0;
     285                 : }
     286                 : 
     287                 : void NaClSimpleRevServiceRpcHandler(
     288                 :     struct NaClSimpleRevService     *self,
     289               5 :     struct NaClSimpleRevConnection  *conn) {
     290                 :   int retval;
     291                 : 
     292               5 :   NaClLog(4, "Entered NaClSimpleRevServiceRpcHandler: ServerLoop!\n");
     293               5 :   retval = NaClSrpcServerLoop(conn->connected_socket,
     294                 :                               self->handlers,
     295                 :                               conn->instance_data);
     296               5 :   NaClLog(4,
     297                 :           "NaClSimpleRevServiceRpcHandler: NaClSrpcServerLoop returned %d\n",
     298                 :           retval);
     299               5 :   if (NULL != conn->exit_cb) {
     300               2 :     (*conn->exit_cb)(conn->instance_data, retval);
     301                 :   }
     302               5 :   NaClLog(4, "Leaving NaClSimpleRevServiceRpcHandler\n");
     303               5 : }
     304                 : 
     305                 : struct NaClSimpleRevServiceVtbl const kNaClSimpleRevServiceVtbl = {
     306                 :   {
     307                 :     NaClSimpleRevServiceDtor,
     308                 :   },
     309                 :   NaClSimpleRevServiceConnectAndSpawnHandler,
     310                 :   NaClSimpleRevServiceConnectAndSpawnHandlerCb,
     311                 :   NaClSimpleRevServiceConnectionFactory,
     312                 :   NaClSimpleRevServiceRpcHandler,
     313                 : };
     314                 : 
     315                 : int NaClSimpleRevConnectionCtor(
     316                 :     struct NaClSimpleRevConnection  *self,
     317                 :     struct NaClSimpleRevService     *service,
     318                 :     struct NaClDesc                 *conn,
     319                 :     void                            (*exit_cb)(void *instance_data,
     320                 :                                                int  server_loop_ret),
     321               5 :     void                            *instance_data) {
     322               5 :   NaClLog(4,
     323                 :           "NaClSimpleRevConnectionCtor: this 0x%"NACL_PRIxPTR"\n",
     324                 :           (uintptr_t) self);
     325               5 :   if (!NaClRefCountCtor(&self->base)) {
     326               0 :     return 0;
     327                 :   }
     328                 : 
     329               5 :   self->service = service;
     330               5 :   self->connected_socket = conn;
     331               5 :   self->exit_cb = exit_cb;
     332               5 :   self->instance_data = instance_data;
     333                 : 
     334               5 :   return 1;
     335                 : }
     336                 : 
     337               0 : void NaClSimpleRevConnectionDtor(struct NaClRefCount *vself) {
     338                 :   struct NaClSimpleRevConnection *self =
     339               0 :       (struct NaClSimpleRevConnection *) vself;
     340                 : 
     341               0 :   NaClRefCountUnref((struct NaClRefCount *) self->service);
     342               0 :   NaClRefCountUnref((struct NaClRefCount *) self->connected_socket);
     343                 : 
     344               0 :   NACL_VTBL(NaClRefCount, self) = &kNaClRefCountVtbl;
     345               0 :   (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
     346               0 : }
     347                 : 
     348                 : struct NaClRefCountVtbl kNaClSimpleRevConnectionVtbl = {
     349                 :   NaClSimpleRevConnectionDtor,
     350                 : };

Generated by: LCOV version 1.7