Coverage for /Syzygy/kasko/service_bridge.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
85.7%54630.C++source

Line-by-line coverage:

   1    :  // Copyright 2014 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  
  15    :  #include "syzygy/kasko/service_bridge.h"
  16    :  
  17    :  #include "base/logging.h"
  18    :  #include "base/process/process_handle.h"
  19    :  #include "base/strings/utf_string_conversions.h"
  20    :  #include "syzygy/common/com_utils.h"
  21    :  #include "syzygy/common/rpc/helpers.h"
  22    :  #include "syzygy/kasko/service.h"
  23    :  
  24    :  namespace kasko {
  25    :  namespace {
  26    :  ServiceBridge* g_service_bridge = NULL;
  27    :  }  // namespace
  28    :  }  // namespace kasko
  29    :  
  30    :  // RPC calls all come through this single free function. We use the singleton
  31    :  // g_service_bridge to forward the call to the running Service.
  32    :  boolean KaskoService_SendDiagnosticReport(handle_t IDL_handle,
  33    :                                            unsigned long exception_info_address,
  34    :                                            unsigned long thread_id,
  35    :                                            DumpType minidump_type,
  36    :                                            unsigned long protobuf_length,
  37    :                                            const signed char* protobuf,
  38    :                                            unsigned long crash_keys_size,
  39  E :                                            const CrashKey* crash_keys) {
  40  E :    DCHECK(kasko::g_service_bridge);
  41    :  
  42    :    base::ProcessId client_process_id =
  43  E :        ::common::rpc::GetClientProcessID(IDL_handle);
  44  E :    if (!client_process_id)
  45  i :      return false;
  46    :  
  47  E :    std::map<base::string16, base::string16> crash_keys_map;
  48  E :    for (unsigned long i = 0; i < crash_keys_size; ++i) {
  49  E :      if (!crash_keys[i].name || !crash_keys[i].value)
  50  i :        continue;
  51    :      crash_keys_map[base::UTF8ToUTF16(
  52    :          reinterpret_cast<const char*>(crash_keys[i].name))] =
  53  E :          base::UTF8ToUTF16(reinterpret_cast<const char*>(crash_keys[i].value));
  54  E :    }
  55    :  
  56  E :    kasko::MinidumpType internal_minidump_type = kasko::SMALL_DUMP_TYPE;
  57  E :    switch (minidump_type) {
  58    :      case SMALL_DUMP:
  59  E :        internal_minidump_type = kasko::SMALL_DUMP_TYPE;
  60  E :        break;
  61    :      case LARGER_DUMP:
  62  E :        internal_minidump_type = kasko::LARGER_DUMP_TYPE;
  63  E :        break;
  64    :      case FULL_DUMP:
  65  i :        internal_minidump_type = kasko::FULL_DUMP_TYPE;
  66  i :        break;
  67    :      default:
  68  i :        NOTREACHED();
  69    :        break;
  70    :    }
  71    :  
  72    :    kasko::g_service_bridge->service_->SendDiagnosticReport(
  73    :        client_process_id, exception_info_address, thread_id,
  74    :        internal_minidump_type, reinterpret_cast<const char*>(protobuf),
  75  E :        protobuf_length, crash_keys_map);
  76    :  
  77  E :    return true;
  78  E :  }
  79    :  
  80    :  namespace kasko {
  81    :  
  82    :  ServiceBridge::ServiceBridge(const base::string16& protocol,
  83    :                               const base::string16& endpoint,
  84    :                               scoped_ptr<Service> service)
  85    :      : protocol_(protocol),
  86    :        endpoint_(endpoint),
  87    :        service_(service.Pass()),
  88  E :        running_(false) {
  89    :    // It's a bad idea to have two instances stepping on each other's toes.
  90  E :    CHECK(!g_service_bridge);
  91    :  
  92  E :    DCHECK(!protocol_.empty());
  93  E :    DCHECK(!endpoint_.empty());
  94  E :    DCHECK(service_);
  95  E :    g_service_bridge = this;
  96  E :  }
  97    :  
  98  E :  ServiceBridge::~ServiceBridge() {
  99    :    // It's a bad idea to shut down without stopping the service. It's also a bad
 100    :    // idea to block unexpectedly in our destructor.
 101  E :    CHECK(!running_);
 102    :  
 103  E :    DCHECK_EQ(this, g_service_bridge);
 104  E :    g_service_bridge = NULL;
 105  E :  }
 106    :  
 107  E :  bool ServiceBridge::Run() {
 108  E :    if (running_) return true;
 109    :  
 110    :    RPC_STATUS status = ::RpcServerUseProtseqEp(
 111    :        common::rpc::AsRpcWstr(&protocol_[0]), RPC_C_LISTEN_MAX_CALLS_DEFAULT,
 112  E :        common::rpc::AsRpcWstr(&endpoint_[0]), NULL /* Security descriptor. */);
 113    :  
 114    :    // RPC_S_DUPLICATE_ENDPOINT seems to be possible if a previous instance has
 115    :    // already registered this protocol and endpoint. The end result is still that
 116    :    // the endpoint is properly configured for this protocol.
 117  E :    if (status != RPC_S_OK && status != RPC_S_DUPLICATE_ENDPOINT) {
 118  E :      LOG(ERROR) << "Failed to init RPC protocol: " << ::common::LogWe(status)
 119    :                 << ".";
 120  E :    } else {
 121    :      scoped_ptr<common::rpc::ScopedRpcInterfaceRegistration>
 122    :          interface_registration(new common::rpc::ScopedRpcInterfaceRegistration(
 123  E :              KaskoService_Kasko_v1_0_s_ifspec));
 124    :  
 125  E :      if (interface_registration->status() == RPC_S_OK) {
 126    :        status = ::RpcServerListen(1,  // Minimum number of handler threads.
 127  E :                                   RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE);
 128    :  
 129  E :        if (status != RPC_S_OK) {
 130  i :          LOG(ERROR) << "Failed to run RPC server: " << ::common::LogWe(status)
 131    :                     << ".";
 132  i :        } else {
 133  E :          running_ = true;
 134  E :          interface_registration_ = interface_registration.Pass();
 135    :        }
 136    :      }
 137  E :    }
 138    :  
 139  E :    return running_;
 140  E :  }
 141    :  
 142  E :  void ServiceBridge::Stop() {
 143  E :    if (!running_) return;
 144    :  
 145    :    // This call prevents new requests from being accepted.
 146  E :    RPC_STATUS status = ::RpcMgmtStopServerListening(NULL);
 147  E :    if (status != RPC_S_OK) {
 148    :      // If this fails, we could end up servicing calls in a bad state.
 149  i :      LOG(FATAL) << "Failed to stop the RPC server: " << ::common::LogWe(status)
 150    :                 << ".";
 151    :    }
 152    :  
 153    :    // This call will block until all active requests are completed.
 154  E :    status = ::RpcMgmtWaitServerListen();
 155  E :    if (status != RPC_S_OK) {
 156    :      // If this fails, we could end up servicing calls in a bad state.
 157  i :      LOG(FATAL) << "Failed to wait for RPC server shutdown: "
 158    :                 << ::common::LogWe(status) << ".";
 159    :    }
 160    :  
 161  E :    interface_registration_.reset();
 162  E :    running_ = false;
 163  E :  }
 164    :  
 165    :  }  // namespace kasko

Coverage information generated Thu Mar 26 16:15:41 2015.