LCOV - code coverage report
Current view: directory - src/shared/srpc - rpc_log.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 175 25 14.3 %
Date: 2014-09-25 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2012 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                 : /*
       8                 :  * SRPC utility functions.
       9                 :  */
      10                 : 
      11                 : #include <ctype.h>
      12                 : #include <stdarg.h>
      13                 : #include <stdlib.h>
      14                 : #include <string.h>
      15                 : 
      16                 : #include "native_client/src/include/nacl_assert.h"
      17                 : #include "native_client/src/include/portability.h"
      18                 : #include "native_client/src/include/portability_io.h"
      19                 : #include "native_client/src/include/portability_process.h"
      20                 : 
      21                 : #include "native_client/src/shared/platform/nacl_exit.h"
      22                 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
      23                 : #include "native_client/src/shared/platform/nacl_threads.h"
      24                 : #include "native_client/src/shared/platform/nacl_timestamp.h"
      25                 : #include "native_client/src/shared/srpc/nacl_srpc.h"
      26                 : #include "native_client/src/shared/srpc/nacl_srpc_internal.h"
      27                 : 
      28                 : static struct NaClMutex log_mu;
      29                 : 
      30                 : static int verbosity;
      31                 : 
      32               3 : static void setVerbosityFromEnv(void) {
      33               3 :   const char* env_verbosity = getenv("NACL_SRPC_DEBUG");
      34               3 :   verbosity = 0;
      35               3 :   if (NULL != env_verbosity) {
      36               0 :     int v = strtol(env_verbosity, (char**) 0, 0);
      37               0 :     if (v >= 0) {
      38               0 :       verbosity = v;
      39                 :     }
      40                 :   }
      41               3 : }
      42                 : 
      43               3 : int NaClSrpcLogInit(void) {
      44               3 :   NaClXMutexCtor(&log_mu);
      45               3 :   setVerbosityFromEnv();
      46               3 :   return 1;
      47               3 : }
      48                 : 
      49               3 : void NaClSrpcLogFini(void) {
      50               3 :   NaClMutexDtor(&log_mu);
      51               3 : }
      52                 : 
      53               3 : void NaClSrpcLog(int detail_level, const char* fmt, ...) {
      54                 :   /*
      55                 :    * It would be better to use the NaClLog infrastructure to do this, but
      56                 :    * it requires some more enhancement to be ready.
      57                 :    * http://code.google.com/p/nativeclient/issues/detail?id=1802
      58                 :    * TODO(bsy,sehr): convert this when NaClLog is ready for SRPC levels, etc.
      59                 :    */
      60               3 :   if (detail_level <= verbosity) {
      61                 :     char timestamp[128];
      62               0 :     int pid = GETPID();
      63                 :     va_list ap;
      64               0 :     unsigned tid = NaClThreadId();
      65                 :     const char* ts;
      66                 : #ifdef __native_client__
      67                 :     const char* host_or_nacl = "NACL";
      68                 : #else
      69               0 :     const char* host_or_nacl = "HOST";
      70                 : #endif
      71               0 :     va_start(ap, fmt);
      72               0 :     NaClXMutexLock(&log_mu);
      73               0 :     ts = NaClTimeStampString(timestamp, sizeof timestamp);
      74                 :     fprintf(stderr,
      75                 :             "[SRPC:%s:%d,%"NACL_PRIu32":%s] ",
      76                 :             host_or_nacl,
      77                 :             pid,
      78                 :             tid,
      79               0 :             ts);
      80               0 :     vfprintf(stderr, fmt, ap);
      81               0 :     NaClXMutexUnlock(&log_mu);
      82               0 :     va_end(ap);
      83                 :   }
      84               3 :   if (detail_level == NACL_SRPC_LOG_FATAL) {
      85               0 :     NaClAbort();
      86                 :   }
      87               3 : }
      88                 : 
      89                 : /*
      90                 :  * This makes a best-effort escape sequence to feed sel_universal's parser
      91                 :  * in src/trusted/sel_universal/parsing.cc.
      92                 :  */
      93               0 : static int shouldPrintAsEscaped(int cval) {
      94               0 :   switch (cval) {
      95                 :     case '\0':
      96               0 :       return '0';
      97                 :     case '\\':
      98               0 :       return '\\';
      99                 :     case '\"':
     100               0 :       return '\"';
     101                 :     case '\'':
     102               0 :       return '\'';
     103                 :     case '\a':
     104               0 :       return 'a';
     105                 :     case '\b':
     106               0 :       return 'b';
     107                 :     case '\f':
     108               0 :       return 'f';
     109                 :     case '\n':
     110               0 :       return 'n';
     111                 :     case '\r':
     112               0 :       return 'r';
     113                 :     case '\t':
     114               0 :       return 't';
     115                 :     case '\v':
     116               0 :       return 'v';
     117                 :     default:
     118               0 :       return -1;
     119                 :   }
     120               0 : }
     121                 : 
     122               0 : static void formatChar(int cval, char** buf, size_t* bytes_remaining) {
     123                 :   int escaped_char;
     124               0 :   if (isprint(cval)) {
     125                 :     static const size_t kBytesRequiredForChar = 1;
     126               0 :     if (*bytes_remaining >= kBytesRequiredForChar) {
     127               0 :       **buf = cval;
     128               0 :       *buf += kBytesRequiredForChar;
     129               0 :       *bytes_remaining -= kBytesRequiredForChar;
     130                 :     }
     131               0 :     return;
     132                 :   }
     133               0 :   escaped_char = shouldPrintAsEscaped(cval);
     134               0 :   if (escaped_char != -1) {
     135                 :     static const size_t kBytesRequiredForEscapedChar = 2;
     136               0 :     if (*bytes_remaining >= kBytesRequiredForEscapedChar) {
     137               0 :       (*buf)[0] = '\\';
     138               0 :       (*buf)[1] = escaped_char;
     139               0 :       *buf += kBytesRequiredForEscapedChar;
     140               0 :       *bytes_remaining -= kBytesRequiredForEscapedChar;
     141                 :     }
     142               0 :   } else {
     143                 :     /* SNPRINTF needs space to write the NUL, but reports only the non-NUL
     144                 :      * byte count written. */
     145                 :     static const size_t kBytesRequiredForHex = 4 + 1;
     146               0 :     if (*bytes_remaining >= kBytesRequiredForHex) {
     147                 :       size_t written_bytes =
     148               0 :           SNPRINTF(*buf, kBytesRequiredForHex, "\\x%02x", (unsigned char) cval);
     149               0 :       *buf += written_bytes;
     150               0 :       *bytes_remaining -= written_bytes;
     151                 :     }
     152                 :   }
     153               0 : }
     154                 : 
     155                 : static void formatString(const char* str,
     156                 :                          char** buf,
     157               0 :                          size_t* bytes_remaining) {
     158               0 :   while (*str != 0) {
     159               0 :     formatChar((unsigned char) *str, buf, bytes_remaining);
     160               0 :     ++str;
     161               0 :   }
     162               0 : }
     163                 : 
     164               0 : static void formatDouble(double dval, char** buf, size_t* bytes_remaining) {
     165                 :   char tmp[32];
     166               0 :   SNPRINTF(tmp, sizeof(tmp), "%f", dval);
     167               0 :   formatString(tmp, buf, bytes_remaining);
     168               0 : }
     169                 : 
     170               0 : static void formatCount(uint32_t count, char** buf, size_t* bytes_remaining) {
     171                 :   char tmp[32];
     172               0 :   SNPRINTF(tmp, sizeof(tmp), "%"NACL_PRIu32, count);
     173               0 :   formatString(tmp, buf, bytes_remaining);
     174               0 : }
     175                 : 
     176               0 : static void formatInt(int32_t ival, char** buf, size_t* bytes_remaining) {
     177                 :   char tmp[32];
     178               0 :   SNPRINTF(tmp, sizeof(tmp), "%"NACL_PRId32, ival);
     179               0 :   formatString(tmp, buf, bytes_remaining);
     180               0 : }
     181                 : 
     182               0 : static void formatLong(int64_t lval, char** buf, size_t* bytes_remaining) {
     183                 :   char tmp[32];
     184               0 :   SNPRINTF(tmp, sizeof(tmp), "%"NACL_PRId64, lval);
     185               0 :   formatString(tmp, buf, bytes_remaining);
     186               0 : }
     187                 : 
     188               0 : static void formatPointer(void* pval, char** buf, size_t* bytes_remaining) {
     189                 :   char tmp[32];
     190               0 :   SNPRINTF(tmp, sizeof(tmp), "%p", pval);
     191               0 :   formatString(tmp, buf, bytes_remaining);
     192               0 : }
     193                 : 
     194                 : void NaClSrpcFormatArg(int detail_level,
     195                 :                        const NaClSrpcArg* arg,
     196                 :                        char* buffer,
     197               2 :                        size_t buffer_size) {
     198                 :   uint32_t i;
     199                 : 
     200               2 :   if (detail_level > verbosity) {
     201               2 :     return;
     202                 :   }
     203                 :   /* Reserve space for trailing zero. */
     204               0 :   if (buffer_size == 0) {
     205               0 :     return;
     206                 :   }
     207               0 :   buffer_size--;
     208               0 :   formatChar(arg->tag, &buffer, &buffer_size);
     209               0 :   formatString("(", &buffer, &buffer_size);
     210               0 :   switch (arg->tag) {
     211                 :     case NACL_SRPC_ARG_TYPE_INVALID:
     212                 :       break;
     213                 :     case NACL_SRPC_ARG_TYPE_BOOL:
     214               0 :       formatInt(arg->u.bval, &buffer, &buffer_size);
     215               0 :       break;
     216                 :     case NACL_SRPC_ARG_TYPE_CHAR_ARRAY:
     217               0 :       formatCount(arg->u.count, &buffer, &buffer_size);
     218               0 :       if (arg->arrays.carr == NULL) {
     219               0 :         formatString(",(nil)", &buffer, &buffer_size);
     220               0 :       } else  {
     221               0 :         formatString(",", &buffer, &buffer_size);
     222               0 :         for (i = 0; i < arg->u.count; ++i)
     223               0 :           formatChar(arg->arrays.carr[i], &buffer, &buffer_size);
     224                 :       }
     225               0 :       break;
     226                 :     case NACL_SRPC_ARG_TYPE_DOUBLE:
     227               0 :       formatDouble(arg->u.dval, &buffer, &buffer_size);
     228               0 :       break;
     229                 :     case NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY:
     230               0 :       formatCount(arg->u.count, &buffer, &buffer_size);
     231               0 :       if (arg->arrays.darr == NULL) {
     232               0 :         formatString(",(nil)", &buffer, &buffer_size);
     233               0 :       } else  {
     234               0 :         for (i = 0; i < arg->u.count; ++i) {
     235               0 :           formatString(",", &buffer, &buffer_size);
     236               0 :           formatDouble(arg->arrays.darr[i], &buffer, &buffer_size);
     237               0 :         }
     238                 :       }
     239               0 :       break;
     240                 :     case NACL_SRPC_ARG_TYPE_HANDLE:
     241               0 :       formatPointer((void*) arg->u.hval, &buffer, &buffer_size);
     242               0 :       break;
     243                 :     case NACL_SRPC_ARG_TYPE_INT:
     244               0 :       formatInt(arg->u.ival, &buffer, &buffer_size);
     245               0 :       break;
     246                 :     case NACL_SRPC_ARG_TYPE_INT_ARRAY:
     247               0 :       formatCount(arg->u.count, &buffer, &buffer_size);
     248               0 :       if (arg->arrays.iarr == NULL) {
     249               0 :         formatString(",(nil)", &buffer, &buffer_size);
     250               0 :       } else  {
     251               0 :         for (i = 0; i < arg->u.count; ++i) {
     252               0 :           formatString(",", &buffer, &buffer_size);
     253               0 :           formatInt(arg->arrays.iarr[i], &buffer, &buffer_size);
     254               0 :         }
     255                 :       }
     256               0 :       break;
     257                 :     case NACL_SRPC_ARG_TYPE_LONG:
     258               0 :       formatString("l(", &buffer, &buffer_size);
     259               0 :       formatLong(arg->u.lval, &buffer, &buffer_size);
     260               0 :       break;
     261                 :     case NACL_SRPC_ARG_TYPE_LONG_ARRAY:
     262               0 :       formatCount(arg->u.count, &buffer, &buffer_size);
     263               0 :       if (arg->arrays.larr == NULL) {
     264               0 :         formatString(",(nil)", &buffer, &buffer_size);
     265               0 :       } else  {
     266               0 :         for (i = 0; i < arg->u.count; ++i) {
     267               0 :           formatString(",", &buffer, &buffer_size);
     268               0 :           formatLong(arg->arrays.larr[i], &buffer, &buffer_size);
     269               0 :         }
     270                 :       }
     271               0 :       break;
     272                 :     case NACL_SRPC_ARG_TYPE_STRING:
     273               0 :       if (arg->arrays.str == NULL) {
     274               0 :         formatString("(nil)", &buffer, &buffer_size);
     275               0 :       } else {
     276               0 :         formatString("\"", &buffer, &buffer_size);
     277               0 :         formatString(arg->arrays.str, &buffer, &buffer_size);
     278               0 :         formatString("\"", &buffer, &buffer_size);
     279                 :       }
     280               0 :       break;
     281                 :       /*
     282                 :        * The cases below are added to avoid warnings, they are only used
     283                 :        * in the plugin code
     284                 :        */
     285                 :     case NACL_SRPC_ARG_TYPE_OBJECT:
     286                 :       /* this is a pointer that NaCl module can do nothing with */
     287               0 :       formatPointer(arg->arrays.oval, &buffer, &buffer_size);
     288                 :       break;
     289                 :     case NACL_SRPC_ARG_TYPE_VARIANT_ARRAY:
     290                 :       break;
     291                 :     default:
     292                 :       break;
     293                 :   }
     294               0 :   formatString(")", &buffer, &buffer_size);
     295               0 :   *buffer = '\0';
     296               2 : }
     297                 : 
     298                 : 
     299                 : /*
     300                 :  * Get the printable form of an error code.
     301                 :  */
     302               2 : const char* NaClSrpcErrorString(NaClSrpcError error_code) {
     303               2 :   switch (error_code) {
     304                 :    case NACL_SRPC_RESULT_OK:
     305               2 :      return "No error";
     306                 :    case NACL_SRPC_RESULT_BREAK:
     307               0 :      return "Break out of server RPC loop";
     308                 :    case NACL_SRPC_RESULT_MESSAGE_TRUNCATED:
     309               0 :      return "Received message was shorter than expected";
     310                 :    case NACL_SRPC_RESULT_NO_MEMORY:
     311               0 :      return "Out of memory";
     312                 :    case NACL_SRPC_RESULT_PROTOCOL_MISMATCH:
     313               0 :      return "Client and server have different protocol versions";
     314                 :    case NACL_SRPC_RESULT_BAD_RPC_NUMBER:
     315               0 :      return "No method for the given rpc number";
     316                 :    case NACL_SRPC_RESULT_BAD_ARG_TYPE:
     317               0 :      return "Bad argument type received";
     318                 :    case NACL_SRPC_RESULT_TOO_MANY_ARGS:
     319               0 :      return "Too many arguments (more than NACL_SRPC_MAX_ARGS or declared)";
     320                 :    case NACL_SRPC_RESULT_TOO_FEW_ARGS:
     321               0 :      return "Too few arguments (fewer than declared)";
     322                 :    case NACL_SRPC_RESULT_IN_ARG_TYPE_MISMATCH:
     323               0 :      return "Input argument type mismatch";
     324                 :    case NACL_SRPC_RESULT_OUT_ARG_TYPE_MISMATCH:
     325               0 :      return "Output argument type mismatch";
     326                 :    case NACL_SRPC_RESULT_INTERNAL:
     327               0 :      return "Internal error in rpc method";
     328                 :    case NACL_SRPC_RESULT_APP_ERROR:
     329               0 :      return "Rpc application returned an error";
     330                 :    default:
     331                 :      break;
     332                 :   }
     333               0 :   return "Unrecognized NaClSrpcError value";
     334               2 : }

Generated by: LCOV version 1.7