1 : // Copyright 2015 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/client.h"
16 :
17 : #include <Rpc.h>
18 :
19 : #include <map>
20 : #include <string>
21 :
22 : #include "base/logging.h"
23 : #include "base/memory/scoped_ptr.h"
24 : #include "base/strings/utf_string_conversions.h"
25 : #include "base/threading/platform_thread.h"
26 : #include "syzygy/common/rpc/helpers.h"
27 : #include "syzygy/kasko/kasko_rpc.h"
28 :
29 : namespace kasko {
30 :
31 E : Client::Client(const base::string16& endpoint) : endpoint_(endpoint) {
32 E : }
33 :
34 E : Client::~Client(){
35 E : }
36 :
37 : void Client::SendReport(const EXCEPTION_POINTERS* exception_pointers,
38 : MinidumpType minidump_type,
39 : const char* protobuf,
40 : size_t protobuf_length,
41 : const base::char16* const* keys,
42 E : const base::char16* const* values) const {
43 : // Establish the RPC binding.
44 E : common::rpc::ScopedRpcBinding rpc_binding;
45 E : if (!rpc_binding.Open(L"ncalrpc", endpoint_)) {
46 i : LOG(ERROR) << "Failed to open an RPC binding.";
47 i : return;
48 : }
49 :
50 : // Convert the crash keys to UTF-8.
51 : // TODO(erikwright): These values are repeatedly converted between UTF-8 and
52 : // UTF-16 between the initial client API invocation and the final HTTP upload.
53 : // A single encoding should be adopted from end to end.
54 E : std::map<std::string, std::string> utf8_crash_keys;
55 E : if (keys && values) {
56 E : for (size_t i = 0; keys[i] && values[i]; ++i) {
57 : utf8_crash_keys[base::UTF16ToUTF8(keys[i])] =
58 E : base::UTF16ToUTF8(values[i]);
59 E : }
60 : }
61 :
62 : // Alias the crash key string buffers into the CrashKey array used for the RPC
63 : // invocation.
64 E : scoped_ptr<CrashKey[]> crash_keys(new CrashKey[utf8_crash_keys.size()]);
65 E : size_t index = 0;
66 E : for (const auto& entry : utf8_crash_keys) {
67 : crash_keys[index].name =
68 E : reinterpret_cast<const signed char*>(entry.first.c_str());
69 : crash_keys[index].value =
70 E : reinterpret_cast<const signed char*>(entry.second.c_str());
71 E : ++index;
72 E : }
73 E : DCHECK_EQ(index, utf8_crash_keys.size());
74 :
75 E : DumpType rpc_dump_type = SMALL_DUMP;
76 E : switch (minidump_type) {
77 : case SMALL_DUMP_TYPE:
78 E : rpc_dump_type = SMALL_DUMP;
79 E : break;
80 : case LARGER_DUMP_TYPE:
81 E : rpc_dump_type = LARGER_DUMP;
82 E : break;
83 : case FULL_DUMP:
84 i : rpc_dump_type = FULL_DUMP;
85 i : break;
86 : default:
87 i : NOTREACHED();
88 : break;
89 : }
90 :
91 : // Invoke SendDiagnosticReport via RPC.
92 : common::rpc::RpcStatus status = common::rpc::InvokeRpc(
93 : KaskoClient_SendDiagnosticReport, rpc_binding.Get(),
94 : reinterpret_cast<unsigned long>(exception_pointers),
95 : base::PlatformThread::CurrentId(), rpc_dump_type, protobuf_length,
96 : reinterpret_cast<const signed char*>(protobuf ? protobuf : ""),
97 E : utf8_crash_keys.size(), crash_keys.get());
98 :
99 E : if (!status.succeeded())
100 i : LOG(ERROR) << "Failed to invoke the SendDiagnosticReport RPC.";
101 E : }
102 :
103 : } // namespace kasko
|