1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Broker RPC Client implementation.
#include "ceee/ie/broker/broker_rpc_client.h"
#include <atlbase.h>
#include "base/lock.h"
#include "base/logging.h"
#include "base/win/scoped_comptr.h"
#include "broker_lib.h" // NOLINT
#include "broker_rpc_lib.h" // NOLINT
#include "ceee/common/com_utils.h"
#include "ceee/ie/broker/broker_rpc_utils.h"
BrokerRpcClient::BrokerRpcClient() : context_(0), binding_handle_(NULL) {
}
BrokerRpcClient::~BrokerRpcClient() {
Disconnect();
}
int HandleRpcException(unsigned int rpc_exception_code) {
switch (rpc_exception_code) {
case STATUS_ACCESS_VIOLATION:
case STATUS_DATATYPE_MISALIGNMENT:
case STATUS_PRIVILEGED_INSTRUCTION:
case STATUS_BREAKPOINT:
case STATUS_STACK_OVERFLOW:
case STATUS_IN_PAGE_ERROR:
case STATUS_GUARD_PAGE_VIOLATION:
return EXCEPTION_CONTINUE_SEARCH;
default:
break;
}
return EXCEPTION_EXECUTE_HANDLER;
}
static void LogRpcException(const char* str, unsigned int exception_code) {
LOG(ERROR) << str << com::LogWe(exception_code);
}
void BrokerRpcClient::LockContext() {
RpcTryExcept {
context_ = BrokerRpcClient_Connect(binding_handle_);
} RpcExcept(HandleRpcException(RpcExceptionCode())) {
LogRpcException("RPC error in LockContext", RpcExceptionCode());
} RpcEndExcept
}
void BrokerRpcClient::ReleaseContext() {
RpcTryExcept {
BrokerRpcClient_Disconnect(binding_handle_, &context_);
} RpcExcept(HandleRpcException(RpcExceptionCode())) {
LogRpcException("RPC error in ReleaseContext", RpcExceptionCode());
} RpcEndExcept
}
HRESULT BrokerRpcClient::Connect(bool start_server) {
if (is_connected())
return S_OK;
// Keep alive until RPC is connected.
base::win::ScopedComPtr<ICeeeBrokerRegistrar> broker;
if (start_server) {
// TODO(vitalybuka@google.com): Start broker without COM after the last
// COM interface is removed.
HRESULT hr = broker.CreateInstance(CLSID_CeeeBroker);
LOG_IF(ERROR, FAILED(hr)) << "Failed to create broker. " << com::LogHr(hr);
if (FAILED(hr))
return hr;
}
std::wstring end_point = GetRpcEndPointAddress();
std::wstring protocol = kRpcProtocol;
DCHECK(!protocol.empty());
DCHECK(!end_point.empty());
if (protocol.empty() || end_point.empty())
return RPC_E_FAULT;
// TODO(vitalybuka@google.com): There's no guarantee (aside from name
// uniqueness) that it will connect to an endpoint created by the same user.
// Hint: The missing invocation is RpcBindingSetAuthInfoEx.
LOG(INFO) << "Connecting to RPC server. Endpoint: " << end_point;
RPC_WSTR string_binding = NULL;
// Create binding string with given protocol and end point.
RPC_STATUS status = ::RpcStringBindingCompose(
NULL,
reinterpret_cast<RPC_WSTR>(&protocol[0]),
NULL,
reinterpret_cast<RPC_WSTR>(&end_point[0]),
NULL,
&string_binding);
LOG_IF(ERROR, RPC_S_OK != status) <<
"Failed to compose binding string. RPC_STATUS=0x" << com::LogWe(status);
if (RPC_S_OK == status) {
// Create binding from just generated binding string. Binding handle should
// used for PRC calls.
status = ::RpcBindingFromStringBinding(string_binding, &binding_handle_);
LOG_IF(ERROR, RPC_S_OK != status) <<
"Failed to bind. RPC_STATUS=0x" << com::LogWe(status);
::RpcStringFree(&string_binding);
if (RPC_S_OK == status) {
LOG(INFO) << "RPC client is connected. Endpoint: " << end_point;
LockContext();
}
}
if (!is_connected()) {
Disconnect();
return RPC_E_FAULT;
}
return S_OK;
}
void BrokerRpcClient::Disconnect() {
if (context_ != NULL)
ReleaseContext();
if (binding_handle_ != NULL) {
RPC_STATUS status = ::RpcBindingFree(&binding_handle_);
LOG_IF(WARNING, RPC_S_OK != status) <<
"Failed to unbind. RPC_STATUS=0x" << com::LogWe(status);
}
}
HRESULT BrokerRpcClient::FireEvent(const char* event_name,
const char* event_args) {
RpcTryExcept {
BrokerRpcClient_FireEvent(binding_handle_, event_name, event_args);
return S_OK;
} RpcExcept(HandleRpcException(RpcExceptionCode())) {
LogRpcException("RPC error in FireEvent", RpcExceptionCode());
} RpcEndExcept
return RPC_E_FAULT;
}
bool BrokerRpcClient::SendUmaHistogramTimes(BSTR event_name, int sample) {
RpcTryExcept {
BrokerRpcClient_SendUmaHistogramTimes(binding_handle_, event_name, sample);
return true;
} RpcExcept(HandleRpcException(RpcExceptionCode())) {
LogRpcException("RPC error in SendUmaHistogramTimes", RpcExceptionCode());
} RpcEndExcept
return false;
}
bool BrokerRpcClient::SendUmaHistogramData(BSTR event_name, int sample,
int min, int max, int bucket_count) {
RpcTryExcept {
BrokerRpcClient_SendUmaHistogramData(binding_handle_, event_name, sample,
min, max, bucket_count);
return true;
} RpcExcept(HandleRpcException(RpcExceptionCode())) {
LogRpcException("RPC error in SendUmaHistogramData", RpcExceptionCode());
} RpcEndExcept
return false;
}
|