OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 // | 4 // |
5 // Broker RPC Server implementation. | 5 // Broker RPC Server implementation. |
6 | 6 |
7 #include "ceee/ie/broker/broker_rpc_server.h" | 7 #include "ceee/ie/broker/broker_rpc_server.h" |
8 | 8 |
9 #include "base/atomic_sequence_num.h" | 9 #include "base/atomic_sequence_num.h" |
| 10 #include "base/logging.h" |
10 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
11 #include "base/logging.h" | 12 #include "base/process_util.h" |
12 #include "base/win_util.h" | 13 #include "base/win_util.h" |
13 #include "broker_rpc_lib.h" // NOLINT | 14 #include "broker_rpc_lib.h" // NOLINT |
14 #include "ceee/common/com_utils.h" | 15 #include "ceee/common/com_utils.h" |
15 #include "ceee/ie/broker/broker_module_util.h" | 16 #include "ceee/ie/broker/broker_module_util.h" |
16 #include "ceee/ie/broker/broker_rpc_utils.h" | 17 #include "ceee/ie/broker/broker_rpc_utils.h" |
17 #include "ceee/ie/broker/chrome_postman.h" | 18 #include "ceee/ie/broker/chrome_postman.h" |
18 | 19 |
| 20 |
| 21 namespace { |
19 // This lock ensures that histograms created by the broker are thread safe. | 22 // This lock ensures that histograms created by the broker are thread safe. |
20 // The histograms created here can be initialized on multiple threads. | 23 // The histograms created here can be initialized on multiple threads. |
21 Lock g_metrics_lock; | 24 Lock g_metrics_lock; |
22 | 25 |
| 26 // Endpoint name unique to this process. |
| 27 wchar_t g_server_endpoint[kMaxEndpointSize + 1] = {0}; |
| 28 |
| 29 RPC_STATUS PrepareEndpoint(std::wstring endpoint) { |
| 30 std::wstring protocol = kRpcProtocol; |
| 31 DCHECK(!protocol.empty()); |
| 32 DCHECK(!endpoint.empty()); |
| 33 if (protocol.empty() || endpoint.empty()) |
| 34 return false; |
| 35 LOG(INFO) << "RPC server is starting. Endpoint: " << endpoint; |
| 36 // Tell RPC runtime to use local interprocess communication for given |
| 37 // end point. |
| 38 RPC_STATUS status = ::RpcServerUseProtseqEp( |
| 39 reinterpret_cast<RPC_WSTR>(&protocol[0]), |
| 40 RPC_C_PROTSEQ_MAX_REQS_DEFAULT, |
| 41 reinterpret_cast<RPC_WSTR>(&endpoint[0]), |
| 42 NULL); |
| 43 LOG_IF(ERROR, RPC_S_OK != status && RPC_S_DUPLICATE_ENDPOINT != status) << |
| 44 "Failed to set protocol for RPC end point. RPC_STATUS=0x" << |
| 45 com::LogWe(status); |
| 46 return status; |
| 47 } |
| 48 |
| 49 } // namespace |
| 50 |
23 BrokerRpcServer::BrokerRpcServer() | 51 BrokerRpcServer::BrokerRpcServer() |
24 : is_started_(false), | 52 : is_started_(false), |
25 current_thread_(::GetCurrentThreadId()) { | 53 current_thread_(::GetCurrentThreadId()) { |
26 } | 54 } |
27 | 55 |
28 BrokerRpcServer::~BrokerRpcServer() { | 56 BrokerRpcServer::~BrokerRpcServer() { |
29 DCHECK(current_thread_ == ::GetCurrentThreadId()); | 57 DCHECK(current_thread_ == ::GetCurrentThreadId()); |
30 Stop(); | 58 Stop(); |
31 } | 59 } |
32 | 60 |
33 bool BrokerRpcServer::Start() { | 61 bool BrokerRpcServer::Start() { |
34 DCHECK(current_thread_ == ::GetCurrentThreadId()); | 62 DCHECK(current_thread_ == ::GetCurrentThreadId()); |
35 | 63 |
36 if (is_started()) | 64 if (is_started()) |
37 return true; | 65 return true; |
38 | 66 |
39 std::wstring end_point = GetRpcEndPointAddress(); | 67 std::wstring endpoint = GetRpcEndpointAddress(); |
40 std::wstring protocol = kRpcProtocol; | 68 |
41 DCHECK(!protocol.empty()); | 69 LOG(INFO) << "Calculating unique endpoint name."; |
42 DCHECK(!end_point.empty()); | 70 const int kMaxTries = 100; |
43 if (protocol.empty() || end_point.empty()) | 71 RPC_STATUS status = RPC_E_FAULT; |
| 72 for (int try_num = 0; try_num < kMaxTries && |
| 73 wcslen(g_server_endpoint) == 0; ++try_num) { |
| 74 std::wostringstream string_builder; |
| 75 string_builder << base::TimeTicks::Now().ToInternalValue() << L"+" << |
| 76 base::GetCurrentProcId() << L"+" << endpoint; |
| 77 std::wstring unique_endpoint = string_builder.str(); |
| 78 unique_endpoint.resize(std::min<size_t>(unique_endpoint.size(), |
| 79 kMaxEndpointSize)); |
| 80 |
| 81 LOG(INFO) << "Unique endpoint:" << unique_endpoint; |
| 82 status = PrepareEndpoint(unique_endpoint); |
| 83 |
| 84 if (status == RPC_S_OK) { // RPC_S_DUPLICATE_ENDPOINT is not accepted. |
| 85 DCHECK(unique_endpoint.size() < arraysize(g_server_endpoint)); |
| 86 wcscpy(g_server_endpoint, unique_endpoint.c_str()); |
| 87 } |
| 88 } |
| 89 |
| 90 if (wcslen(g_server_endpoint) == 0) { |
| 91 DCHECK(status != RPC_S_OK); |
| 92 LOG(ERROR) << "Calculating unique endpoint name failed."; |
44 return false; | 93 return false; |
| 94 } |
45 | 95 |
46 LOG(INFO) << "RPC server is starting. Endpoint: " << end_point; | 96 // Now we can setup fixed endpoint. |
47 // Tell RPC runtime to use local interprocess communication for given | 97 status = PrepareEndpoint(endpoint); |
48 // end point. | 98 |
49 RPC_STATUS status = ::RpcServerUseProtseqEp( | |
50 reinterpret_cast<RPC_WSTR>(&protocol[0]), | |
51 RPC_C_PROTSEQ_MAX_REQS_DEFAULT, | |
52 reinterpret_cast<RPC_WSTR>(&end_point[0]), | |
53 NULL); | |
54 LOG_IF(ERROR, RPC_S_OK != status && RPC_S_DUPLICATE_ENDPOINT != status) << | |
55 "Failed to set protocol for RPC end point. RPC_STATUS=0x" << | |
56 com::LogWe(status); | |
57 if (RPC_S_OK == status || RPC_S_DUPLICATE_ENDPOINT == status) { | 99 if (RPC_S_OK == status || RPC_S_DUPLICATE_ENDPOINT == status) { |
58 // Register RPC interface with the RPC runtime. | 100 // Register RPC interface with the RPC runtime. |
59 status = ::RpcServerRegisterIfEx(BrokerRpcServer_CeeeBroker_v1_1_s_ifspec, | 101 status = ::RpcServerRegisterIfEx(BrokerRpcServer_CeeeBroker_v1_1_s_ifspec, |
60 NULL, NULL, 0, RPC_C_LISTEN_MAX_CALLS_DEFAULT, NULL); | 102 NULL, NULL, 0, RPC_C_LISTEN_MAX_CALLS_DEFAULT, NULL); |
61 LOG_IF(ERROR, RPC_S_OK != status) << | 103 LOG_IF(ERROR, RPC_S_OK != status) << |
62 "Failed to register RPC interface. RPC_STATUS=0x" << com::LogWe(status); | 104 "Failed to register RPC interface. RPC_STATUS=0x" << com::LogWe(status); |
63 if (RPC_S_OK == status) { | 105 if (RPC_S_OK == status) { |
64 // Start listen for RPC calls. | 106 // Start listen for RPC calls. |
65 status = ::RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE); | 107 status = ::RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE); |
66 LOG_IF(ERROR, RPC_S_OK != status) << | 108 LOG_IF(ERROR, RPC_S_OK != status) << |
67 "Failed to start listening. RPC_STATUS=0x" << com::LogWe(status); | 109 "Failed to start listening. RPC_STATUS=0x" << com::LogWe(status); |
68 if (RPC_S_OK == status) { | 110 if (RPC_S_OK == status) { |
69 LOG(INFO) << "RPC server is started. Endpoint: " << end_point; | 111 LOG(INFO) << "RPC server is started. Endpoints: " << endpoint << " " << |
| 112 g_server_endpoint; |
70 is_started_ = true; | 113 is_started_ = true; |
71 } | 114 } |
72 } | 115 } |
73 } | 116 } |
74 if (!is_started()) | 117 if (!is_started()) |
75 Stop(); | 118 Stop(); |
76 | 119 |
77 return is_started(); | 120 return is_started(); |
78 } | 121 } |
79 | 122 |
80 bool BrokerRpcServer::Stop() { | 123 bool BrokerRpcServer::Stop() { |
81 DCHECK(current_thread_ == ::GetCurrentThreadId()); | 124 DCHECK(current_thread_ == ::GetCurrentThreadId()); |
82 is_started_ = false; | 125 is_started_ = false; |
83 // Stop server listening for RPC. | 126 // Stop server listening for RPC. |
84 RPC_STATUS status = ::RpcMgmtStopServerListening(NULL); | 127 RPC_STATUS status = ::RpcMgmtStopServerListening(NULL); |
85 LOG_IF(WARNING, RPC_S_OK != status) << | 128 LOG_IF(WARNING, RPC_S_OK != status) << |
86 "Failed to stop listening. RPC_STATUS=0x" << com::LogWe(status); | 129 "Failed to stop listening. RPC_STATUS=0x" << com::LogWe(status); |
87 // Wait while server stops listening threads. | 130 // Wait while server stops listening threads. |
88 status = ::RpcMgmtWaitServerListen(); | 131 status = ::RpcMgmtWaitServerListen(); |
89 LOG_IF(WARNING, RPC_S_OK != status) << | 132 LOG_IF(WARNING, RPC_S_OK != status) << |
90 "Failed to wait server listen. RPC_STATUS=0x" << com::LogWe(status); | 133 "Failed to wait server listen. RPC_STATUS=0x" << com::LogWe(status); |
91 // Unregister RPC interface. | 134 // Unregister RPC interface. |
92 status = ::RpcServerUnregisterIf( | 135 status = ::RpcServerUnregisterIf( |
93 BrokerRpcServer_CeeeBroker_v1_1_s_ifspec, NULL, FALSE); | 136 BrokerRpcServer_CeeeBroker_v1_1_s_ifspec, NULL, FALSE); |
94 LOG_IF(WARNING, RPC_S_OK != status) << | 137 LOG_IF(WARNING, RPC_S_OK != status) << |
95 "Failed to unregister interface. RPC_STATUS=0x" << com::LogWe(status); | 138 "Failed to unregister interface. RPC_STATUS=0x" << com::LogWe(status); |
| 139 |
| 140 g_server_endpoint[0] = 0; |
| 141 |
96 return RPC_S_OK == status; | 142 return RPC_S_OK == status; |
97 } | 143 } |
98 | 144 |
99 bool BrokerRpcServer::is_started() const { | 145 bool BrokerRpcServer::is_started() const { |
100 DCHECK(current_thread_ == ::GetCurrentThreadId()); | 146 DCHECK(current_thread_ == ::GetCurrentThreadId()); |
101 return is_started_; | 147 return is_started_; |
102 } | 148 } |
103 | 149 |
104 static base::AtomicSequenceNumber current_broker_rpc_context( | 150 static base::AtomicSequenceNumber current_broker_rpc_context( |
105 base::LINKER_INITIALIZED); | 151 base::LINKER_INITIALIZED); |
106 | 152 |
| 153 int BrokerRpcServer_GetServerEndpoint(handle_t handle, int max_size, |
| 154 wchar_t* endpoint) { |
| 155 endpoint[0] = 0; |
| 156 int endpoint_size = wcslen(g_server_endpoint); |
| 157 if (endpoint_size < max_size) |
| 158 wcscpy(endpoint, g_server_endpoint); |
| 159 return endpoint_size; |
| 160 } |
| 161 |
107 BrokerContextHandle BrokerRpcServer_Connect(handle_t binding_handle) { | 162 BrokerContextHandle BrokerRpcServer_Connect(handle_t binding_handle) { |
108 // TODO(vitalybuka@google.com): Add client identity check. | 163 // TODO(vitalybuka@google.com): Add client identity check. |
109 ceee_module_util::LockModule(); | 164 ceee_module_util::LockModule(); |
110 return reinterpret_cast<void*>(current_broker_rpc_context.GetNext() + 1); | 165 return reinterpret_cast<void*>(current_broker_rpc_context.GetNext() + 1); |
111 } | 166 } |
112 | 167 |
113 void BrokerRpcServer_Disconnect( | 168 void BrokerRpcServer_Disconnect( |
114 handle_t binding_handle, | 169 handle_t binding_handle, |
115 BrokerContextHandle* context) { | 170 BrokerContextHandle* context) { |
116 DCHECK(context != NULL); | 171 DCHECK(context != NULL); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 // We can't unfortunately use the HISTOGRAM_*_COUNT here because they use | 213 // We can't unfortunately use the HISTOGRAM_*_COUNT here because they use |
159 // static variables to save time. | 214 // static variables to save time. |
160 AutoLock lock(g_metrics_lock); | 215 AutoLock lock(g_metrics_lock); |
161 scoped_refptr<base::Histogram> counter = | 216 scoped_refptr<base::Histogram> counter = |
162 base::Histogram::FactoryGet(name, min, max, bucket_count, | 217 base::Histogram::FactoryGet(name, min, max, bucket_count, |
163 base::Histogram::kUmaTargetedHistogramFlag); | 218 base::Histogram::kUmaTargetedHistogramFlag); |
164 DCHECK_EQ(name, counter->histogram_name()); | 219 DCHECK_EQ(name, counter->histogram_name()); |
165 if (counter.get()) | 220 if (counter.get()) |
166 counter->AddTime(base::TimeDelta::FromMilliseconds(sample)); | 221 counter->AddTime(base::TimeDelta::FromMilliseconds(sample)); |
167 } | 222 } |
OLD | NEW |