LCOV - code coverage report
Current view: directory - src/trusted/sel_universal - replay_handler.cc (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 87 3 3.4 %
Date: 2012-02-16 Functions: 0 0 -

       1                 : // Copyright (c) 2011 The Native Client Authors. All rights reserved.
       2                 : // Use of this source code is governed by a BSD-style license that can be
       3                 : // found in the LICENSE file.
       4                 : //
       5                 : 
       6                 : // Note: this file implements a simple replay engine for srpcs.
       7                 : //       For simplicity this replay engine contains
       8                 : //       some global data structures but since we only
       9                 : //       expect to have a single NaClCommandLoop instance that
      10                 : //       should not matter.
      11                 : #include "native_client/src/include/portability.h"
      12                 : #include "native_client/src/shared/srpc/nacl_srpc.h"
      13                 : #include "native_client/src/shared/platform/nacl_log.h"
      14                 : #include "native_client/src/trusted/sel_universal/parsing.h"
      15                 : #include "native_client/src/trusted/sel_universal/replay_handler.h"
      16                 : #include "native_client/src/trusted/sel_universal/rpc_universal.h"
      17                 : 
      18                 : 
      19                 : #include <stdio.h>
      20                 : #include <iterator>
      21                 : #include <algorithm>
      22                 : #include <string>
      23                 : #include <vector>
      24                 : #include <set>
      25                 : 
      26                 : using std::string;
      27                 : using std::vector;
      28                 : using std::set;
      29                 : 
      30                 : namespace {
      31                 : 
      32                 : 
      33               0 : struct ReplayItem {
      34                 :   int count;
      35                 :   string signature;
      36                 :   vector<string> args_in;
      37                 :   vector<string> args_out;
      38                 : };
      39                 : 
      40                 : // terminated if we cannot find a replay
      41                 : bool GlobalReplayStrict = true;
      42                 : 
      43                 : // List of all "canned" rpcs, order is important
      44              22 : vector<ReplayItem*> GlobalReplayList;
      45                 : 
      46                 : // ugly hack to have access to the NaClCommandLoop even when processing an rpc
      47                 : NaClCommandLoop* GlobalCommandLoop;
      48                 : 
      49                 : // Match a signature and a given set of input args against a replay time.
      50                 : // Return true if this item is a match that could be replayed
      51                 : bool RpcMatchesReplayItem(string signature,
      52                 :                           NaClSrpcArg** inputs,
      53               0 :                           ReplayItem* ri) {
      54                 :   UNREFERENCED_PARAMETER(inputs);
      55                 :   // first check cound and signature
      56               0 :   if (ri->signature != signature) return false;
      57               0 :   if (ri->count == 0 ) return false;
      58                 : 
      59               0 :   NaClLog(2, "found potential match for %s\n", signature.c_str());
      60                 : 
      61                 :   // now for the more costly parameter comparison
      62                 :   // Build the input parameter values.
      63               0 :   const size_t n = ri->args_in.size();
      64                 :   NaClSrpcArg  in[NACL_SRPC_MAX_ARGS];
      65                 :   NaClSrpcArg* inv[NACL_SRPC_MAX_ARGS + 1];
      66               0 :   BuildArgVec(inv, in, n);
      67               0 :   if (!ParseArgs(inv,  ri->args_in, 0, true, GlobalCommandLoop)) {
      68                 :     // TODO(sehr): reclaim memory here on failure.
      69               0 :     NaClLog(LOG_ERROR, "Bad input args for RPC.\n");
      70               0 :     return false;
      71                 :   }
      72                 : 
      73               0 :   const bool result = AllArgsEqual(inv, inputs);
      74               0 :   FreeArrayArgs(inv);
      75               0 :   return result;
      76                 : }
      77                 : 
      78                 : 
      79                 : void ReplayRpc(NaClSrpcRpc* rpc,
      80                 :                NaClSrpcArg** inputs,
      81                 :                NaClSrpcArg** outputs,
      82               0 :                NaClSrpcClosure* done) {
      83                 :   // we just control from the nexe - clean the pipes
      84               0 :   fflush(stdout);
      85               0 :   fflush(stderr);
      86                 : 
      87                 :   const char* rpc_name;
      88                 :   const char* arg_types;
      89                 :   const char* ret_types;
      90                 : 
      91               0 :   if (!NaClSrpcServiceMethodNameAndTypes(rpc->channel->server,
      92                 :                                         rpc->rpc_number,
      93                 :                                         &rpc_name,
      94                 :                                         &arg_types,
      95                 :                                         &ret_types)) {
      96               0 :     NaClLog(LOG_ERROR, "cannot find signature for rpc %d\n", rpc->rpc_number);
      97               0 :     rpc->result = NACL_SRPC_RESULT_APP_ERROR;
      98               0 :     done->Run(done);
      99               0 :     return;
     100                 :   }
     101                 : 
     102                 :   NaClLog(1, "attempt to replay: %s (%s) -> %s\n",
     103               0 :           rpc_name, arg_types, ret_types);
     104                 : 
     105               0 :   string signature = string(rpc_name) + ":" +  arg_types + ":" + ret_types;
     106               0 :   for (size_t i = 0; i < GlobalReplayList.size(); ++i) {
     107               0 :     if (!RpcMatchesReplayItem(signature, inputs, GlobalReplayList[i])) {
     108               0 :       continue;
     109                 :     }
     110               0 :     NaClLog(1, "found replay rpc\n");
     111               0 :     if (!ParseArgs(outputs,
     112                 :                    GlobalReplayList[i]->args_out,
     113                 :                    0,
     114                 :                    true,
     115                 :                    GlobalCommandLoop)) {
     116               0 :       NaClLog(LOG_ERROR, "Bad input args for RPC.\n");
     117               0 :       break;
     118                 :     }
     119                 : 
     120               0 :     printf("replaying %s:\n", signature.c_str());
     121               0 :     GlobalCommandLoop->DumpArgsAndResults(inputs, outputs);
     122                 : 
     123               0 :     rpc->result = NACL_SRPC_RESULT_OK;
     124               0 :     NaClLog(1, "invoke callback\n");
     125               0 :     --GlobalReplayList[i]->count;
     126               0 :     done->Run(done);
     127               0 :     return;
     128                 :   }
     129                 : 
     130               0 :   NaClLog(LOG_WARNING, "No replay rpc found for rpc %s, args:\n", rpc_name);
     131               0 :   for (size_t i = 0; inputs[i] != 0; ++i) {
     132               0 :     string value = DumpArg(inputs[i], GlobalCommandLoop);
     133               0 :     NaClLog(LOG_WARNING, "input %d:  %s\n", (int) i, value.c_str());
     134                 :   }
     135                 : 
     136                 :   // if we exit the for loop here we have an error
     137               0 :   rpc->result = NACL_SRPC_RESULT_APP_ERROR;
     138               0 :   done->Run(done);
     139                 : 
     140               0 :   if (GlobalReplayStrict) {
     141               0 :     exit(-1);
     142               0 :   }
     143                 : }
     144                 : }  // end namespace
     145                 : 
     146                 : 
     147                 : // Register a new replay item
     148               0 : bool HandlerReplay(NaClCommandLoop* ncl, const vector<string>& args) {
     149                 :   UNREFERENCED_PARAMETER(ncl);
     150                 :   // we need three args at start and the "*" in out separator
     151               0 :   if (args.size() < 4) {
     152               0 :     NaClLog(LOG_ERROR, "Insufficient arguments to 'rpc' command.\n");
     153               0 :     return false;
     154                 :   }
     155                 : 
     156                 :   // NOTE: small leak here
     157               0 :   ReplayItem* ri = new ReplayItem;
     158               0 :   ri->count = strtoul(args[1].c_str(), 0, 0);
     159               0 :   ri->signature = args[2];
     160                 : 
     161                 :   // TODO(robertm): use stl find
     162                 :   size_t in_out_sep;
     163               0 :   for (in_out_sep = 3; in_out_sep < args.size(); ++in_out_sep) {
     164               0 :     if (args[in_out_sep] ==  "*")
     165               0 :       break;
     166                 :   }
     167                 : 
     168               0 :   if (in_out_sep == args.size()) {
     169               0 :     NaClLog(LOG_ERROR, "Missing input/output argument separator\n");
     170               0 :     return false;
     171                 :   }
     172                 : 
     173                 :   copy(args.begin() + 3,
     174                 :        args.begin() + in_out_sep,
     175               0 :        back_inserter(ri->args_in));
     176                 :   copy(args.begin() + in_out_sep + 1,
     177                 :        args.end(),
     178               0 :        back_inserter(ri->args_out));
     179                 : 
     180               0 :   GlobalReplayList.push_back(ri);
     181               0 :   return true;
     182                 : }
     183                 : 
     184                 : // Add srpc upcall for all replay signatures registered so far
     185               0 : bool HandlerReplayActivate(NaClCommandLoop* ncl, const vector<string>& args) {
     186               0 :   if (args.size() != 1) {
     187               0 :     NaClLog(LOG_ERROR, "not the right number of args for this command\n");
     188               0 :     return false;
     189                 :   }
     190                 : 
     191               0 :   set<string> sigs;
     192               0 :   for (size_t i = 0; i < GlobalReplayList.size(); ++i) {
     193               0 :     sigs.insert(GlobalReplayList[i]->signature);
     194                 :   }
     195                 : 
     196               0 :   for (set<string>::iterator it = sigs.begin(); it != sigs.end(); ++it) {
     197               0 :     ncl->AddUpcallRpc(*it, ReplayRpc);
     198                 :   }
     199                 :   // ugly hack
     200               0 :   GlobalCommandLoop = ncl;
     201               0 :   return true;
     202                 : }
     203                 : 
     204                 : // Report all unused replays - add the end of a tests there should be none
     205               0 : bool HandlerUnusedReplays(NaClCommandLoop* ncl, const vector<string>& args) {
     206                 :   UNREFERENCED_PARAMETER(ncl);
     207                 :   UNREFERENCED_PARAMETER(args);
     208                 :   // we need three args at start and the "*" in out separator
     209               0 :   for (size_t i = 0; i < GlobalReplayList.size(); ++i) {
     210               0 :     ReplayItem* ri = GlobalReplayList[i];
     211               0 :     if (ri->count == 0) continue;
     212                 : 
     213               0 :     printf("%d %s\n", ri->count, ri->signature.c_str());
     214               0 :     for (size_t j = 0; j < ri->args_in.size(); ++j) {
     215               0 :       printf("in  %d %s\n", static_cast<int>(j), ri->args_in[j].c_str());
     216                 :     }
     217               0 :     for (size_t j = 0; j < ri->args_out.size(); ++j) {
     218               0 :       printf("out %d %s\n", static_cast<int>(j), ri->args_out[j].c_str());
     219                 :     }
     220                 :   }
     221               0 :   return true;
     222              22 : }

Generated by: LCOV version 1.7