1 : // Copyright 2012 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 : // Helper functions to wrap RPC invocations.
16 :
17 : #ifndef SYZYGY_COMMON_RPC_HELPERS_H_
18 : #define SYZYGY_COMMON_RPC_HELPERS_H_
19 :
20 : #include <rpc.h>
21 : #include <wtypes.h>
22 :
23 : #include "base/macros.h"
24 : #include "base/process/process_handle.h"
25 : #include "base/strings/string_piece.h"
26 :
27 : // TODO(rogerm): Is there directly usable stuff in base/callback.h that
28 : // might make this simpler/cleaner?
29 :
30 : namespace common {
31 : namespace rpc {
32 :
33 : // Create an RPC binding.
34 : //
35 : // @param protocol The RPC protocol to bind.
36 : // @param endpoint The endpoint/address to bind.
37 : // @param out_handle A handle to the rpc binding will be returned here.
38 : //
39 : // @returns true on success.
40 : bool CreateRpcBinding(const base::StringPiece16& protocol,
41 : const base::StringPiece16& endpoint,
42 : handle_t* out_handle);
43 :
44 : // Retrieves the PID for the RPC client process.
45 : //
46 : // @param binding An RPC binding.
47 : // @returns The client PID on success, or 0.
48 : base::ProcessId GetClientProcessID(handle_t binding);
49 :
50 : // Generic RPC call return structure. The ReturnType must be able to be
51 : // initialized with a zero.
52 : template<typename ReturnType>
53 : struct RpcResult {
54 E : RpcResult() : exception_occurred(FALSE), result(0) {}
55 :
56 : boolean exception_occurred;
57 : ReturnType result;
58 :
59 E : bool succeeded() const {
60 E : return exception_occurred == FALSE;
61 E : }
62 : };
63 :
64 : // Specialization of RpcResult used by most RPC calls.
65 : template<>
66 : struct RpcResult<boolean> {
67 E : RpcResult() : exception_occurred(FALSE), result(FALSE) {}
68 :
69 : boolean exception_occurred;
70 : boolean result;
71 :
72 E : bool succeeded() const {
73 E : return exception_occurred == FALSE && result == TRUE;
74 E : }
75 : };
76 : using RpcStatus = RpcResult<boolean>;
77 :
78 : // Helper to invoke an RPC function. Handles any number of paramters and auto
79 : // infers the return type based on the function signature.
80 : template<typename Func, typename ...Params>
81 : RpcResult<decltype(std::declval<Func>()(std::declval<Params>()...))>
82 i : InvokeRpc(const Func& func, Params... params) {
83 : using ReturnType = decltype(std::declval<Func>()(std::declval<Params>()...));
84 i : RpcResult<ReturnType> status;
85 i : RpcTryExcept {
86 i : status.result = func(params...);
87 i : } RpcExcept(1) {
88 i : status.exception_occurred = TRUE;
89 : } RpcEndExcept;
90 i : return status;
91 i : }
92 :
93 : // A helper function to get an @p instance_id specialized version of the
94 : // given @p root string.
95 : std::wstring GetInstanceString(const base::StringPiece16& root,
96 : const base::StringPiece16& instance_id);
97 :
98 : // A helper class to manage an RPC binding handle.
99 : class ScopedRpcBinding {
100 : public:
101 : ScopedRpcBinding();
102 : ~ScopedRpcBinding();
103 :
104 : // @returns the underlying RPC handle.
105 E : handle_t Get() const { return rpc_binding_; }
106 :
107 : // Opens an RPC connection to @p endpoint using @p protocol.
108 : bool Open(const base::StringPiece16& protocol,
109 : const base::StringPiece16& endpoint);
110 :
111 : // Closes this RPC connection.
112 : bool Close();
113 :
114 : protected:
115 : // The OS level binding to the RPC layer.
116 : handle_t rpc_binding_;
117 :
118 : private:
119 : DISALLOW_COPY_AND_ASSIGN(ScopedRpcBinding);
120 : };
121 :
122 : // A helper to manage an RPC interface registration.
123 : class ScopedRpcInterfaceRegistration {
124 : public:
125 : explicit ScopedRpcInterfaceRegistration(RPC_IF_HANDLE if_spec);
126 : ~ScopedRpcInterfaceRegistration();
127 :
128 : RPC_STATUS status() { return status_; }
129 :
130 : private:
131 : RPC_IF_HANDLE if_spec_;
132 : RPC_STATUS status_;
133 : };
134 :
135 : namespace internal {
136 :
137 : template <class T>
138 : struct dereference_pointer;
139 :
140 : template <class T>
141 : struct dereference_pointer<T*> {
142 : typedef T value;
143 : };
144 :
145 : } // namespace internal
146 :
147 : template <class T>
148 E : RPC_WSTR AsRpcWstr(T* value) {
149 : static_assert(
150 : sizeof(internal::dereference_pointer<RPC_WSTR>::value) == sizeof(T),
151 : "Type is incompatible.");
152 E : return reinterpret_cast<RPC_WSTR>(value);
153 E : }
154 :
155 : } // namespace rpc
156 : } // namespace common
157 :
158 : #endif // SYZYGY_COMMON_RPC_HELPERS_H_
|