Coverage for /Syzygy/kasko/service_bridge.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
89.2%66740.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 <windows.h>  // NOLINT
  18    :  #include <rpc.h>
  19    :  #include <stdint.h>
  20    :  
  21    :  #include "base/logging.h"
  22    :  #include "base/process/process_handle.h"
  23    :  #include "syzygy/common/com_utils.h"
  24    :  #include "syzygy/common/rpc/helpers.h"
  25    :  #include "syzygy/kasko/minidump_request.h"
  26    :  #include "syzygy/kasko/service.h"
  27    :  
  28    :  namespace kasko {
  29    :  namespace {
  30    :  ServiceBridge* g_service_bridge = NULL;
  31    :  }  // namespace
  32    :  }  // namespace kasko
  33    :  
  34    :  // RPC calls all come through this single free function. We use the singleton
  35    :  // g_service_bridge to forward the call to the running Service.
  36    :  boolean KaskoService_SendDiagnosticReport(handle_t IDL_handle,
  37  E :                                            MinidumpRequest request) {
  38  E :    DCHECK(kasko::g_service_bridge);
  39    :  
  40    :    base::ProcessId client_process_id =
  41  E :        ::common::rpc::GetClientProcessID(IDL_handle);
  42  E :    if (!client_process_id)
  43  i :      return false;
  44    :  
  45  E :    kasko::MinidumpRequest internal_request;
  46    :  
  47  E :    internal_request.client_exception_pointers = true;
  48  E :    internal_request.exception_info_address = request.exception_info_address;
  49    :  
  50  E :    switch (request.type) {
  51    :      case SMALL_DUMP:
  52  E :        internal_request.type = kasko::MinidumpRequest::SMALL_DUMP_TYPE;
  53  E :        break;
  54    :      case LARGER_DUMP:
  55  E :        internal_request.type = kasko::MinidumpRequest::LARGER_DUMP_TYPE;
  56  E :        break;
  57    :      case FULL_DUMP:
  58  E :        internal_request.type = kasko::MinidumpRequest::FULL_DUMP_TYPE;
  59  E :        break;
  60    :      default:
  61  i :        NOTREACHED();
  62    :        break;
  63    :    }
  64    :  
  65  E :    for (unsigned long i = 0; i < request.user_selected_memory_ranges_size; ++i) {
  66    :      kasko::MinidumpRequest::MemoryRange internal_memory_range = {
  67    :          static_cast<uint32_t>(
  68    :              request.user_selected_memory_ranges[i].base_address),
  69  E :          static_cast<uint32_t>(request.user_selected_memory_ranges[i].length)};
  70    :      internal_request.user_selected_memory_ranges.push_back(
  71  E :          internal_memory_range);
  72  E :    }
  73    :  
  74  E :    for (unsigned long i = 0; i < request.crash_keys_size; ++i) {
  75  E :      if (!request.crash_keys[i].name || !request.crash_keys[i].value)
  76  i :        continue;
  77    :  
  78    :      internal_request.crash_keys.push_back(kasko::MinidumpRequest::CrashKey(
  79  E :          request.crash_keys[i].name, request.crash_keys[i].value));
  80  E :    }
  81    :  
  82  E :    for (unsigned long i = 0; i < request.custom_streams_size; ++i) {
  83  E :      if (!request.custom_streams[i].size)
  84  i :        continue;
  85    :      kasko::MinidumpRequest::CustomStream internal_custom_stream = {
  86    :          request.custom_streams[i].type,
  87    :          reinterpret_cast<const void*>(request.custom_streams[i].data),
  88  E :          request.custom_streams[i].size};
  89  E :      internal_request.custom_streams.push_back(internal_custom_stream);
  90  E :    }
  91    :  
  92    :    kasko::g_service_bridge->service_->SendDiagnosticReport(
  93  E :        client_process_id, request.thread_id, internal_request);
  94    :  
  95  E :    return true;
  96  E :  }
  97    :  
  98    :  namespace kasko {
  99    :  
 100    :  ServiceBridge::ServiceBridge(const base::string16& protocol,
 101    :                               const base::string16& endpoint,
 102    :                               scoped_ptr<Service> service)
 103    :      : protocol_(protocol),
 104    :        endpoint_(endpoint),
 105    :        service_(service.Pass()),
 106  E :        running_(false) {
 107    :    // It's a bad idea to have two instances stepping on each other's toes.
 108  E :    CHECK(!g_service_bridge);
 109    :  
 110  E :    DCHECK(!protocol_.empty());
 111  E :    DCHECK(!endpoint_.empty());
 112  E :    DCHECK(service_);
 113  E :    g_service_bridge = this;
 114  E :  }
 115    :  
 116  E :  ServiceBridge::~ServiceBridge() {
 117    :    // It's a bad idea to shut down without stopping the service. It's also a bad
 118    :    // idea to block unexpectedly in our destructor.
 119  E :    CHECK(!running_);
 120    :  
 121  E :    DCHECK_EQ(this, g_service_bridge);
 122  E :    g_service_bridge = NULL;
 123  E :  }
 124    :  
 125  E :  bool ServiceBridge::Run() {
 126  E :    if (running_) return true;
 127    :  
 128    :    RPC_STATUS status = ::RpcServerUseProtseqEp(
 129    :        common::rpc::AsRpcWstr(&protocol_[0]), RPC_C_LISTEN_MAX_CALLS_DEFAULT,
 130  E :        common::rpc::AsRpcWstr(&endpoint_[0]), NULL /* Security descriptor. */);
 131    :  
 132    :    // RPC_S_DUPLICATE_ENDPOINT seems to be possible if a previous instance has
 133    :    // already registered this protocol and endpoint. The end result is still that
 134    :    // the endpoint is properly configured for this protocol.
 135  E :    if (status != RPC_S_OK && status != RPC_S_DUPLICATE_ENDPOINT) {
 136  E :      LOG(ERROR) << "Failed to init RPC protocol: " << ::common::LogWe(status)
 137    :                 << ".";
 138  E :    } else {
 139    :      scoped_ptr<common::rpc::ScopedRpcInterfaceRegistration>
 140    :          interface_registration(new common::rpc::ScopedRpcInterfaceRegistration(
 141  E :              KaskoService_Kasko_v1_0_s_ifspec));
 142    :  
 143  E :      if (interface_registration->status() == RPC_S_OK) {
 144    :        status = ::RpcServerListen(1,  // Minimum number of handler threads.
 145  E :                                   RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE);
 146    :  
 147  E :        if (status != RPC_S_OK) {
 148  i :          LOG(ERROR) << "Failed to run RPC server: " << ::common::LogWe(status)
 149    :                     << ".";
 150  i :        } else {
 151  E :          running_ = true;
 152  E :          interface_registration_ = interface_registration.Pass();
 153    :        }
 154    :      }
 155  E :    }
 156    :  
 157  E :    return running_;
 158  E :  }
 159    :  
 160  E :  void ServiceBridge::Stop() {
 161  E :    if (!running_) return;
 162    :  
 163    :    // This call prevents new requests from being accepted.
 164  E :    RPC_STATUS status = ::RpcMgmtStopServerListening(NULL);
 165  E :    if (status != RPC_S_OK) {
 166    :      // If this fails, we could end up servicing calls in a bad state.
 167  i :      LOG(FATAL) << "Failed to stop the RPC server: " << ::common::LogWe(status)
 168    :                 << ".";
 169    :    }
 170    :  
 171    :    // This call will block until all active requests are completed.
 172  E :    status = ::RpcMgmtWaitServerListen();
 173  E :    if (status != RPC_S_OK) {
 174    :      // If this fails, we could end up servicing calls in a bad state.
 175  i :      LOG(FATAL) << "Failed to wait for RPC server shutdown: "
 176    :                 << ::common::LogWe(status) << ".";
 177    :    }
 178    :  
 179  E :    interface_registration_.reset();
 180  E :    running_ = false;
 181  E :  }
 182    :  
 183    :  }  // namespace kasko

Coverage information generated Thu Jan 14 17:40:38 2016.