1/*
2 * Copyright (C) 2010-2016 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include "ArgumentCoders.h"
29#include <wtf/CompletionHandler.h>
30#include <wtf/StdLibExtras.h>
31
32namespace IPC {
33
34class Connection;
35
36// Dispatch functions with no reply arguments.
37
38template <typename C, typename MF, typename ArgsTuple, size_t... ArgsIndex>
39void callMemberFunctionImpl(C* object, MF function, ArgsTuple&& args, std::index_sequence<ArgsIndex...>)
40{
41 (object->*function)(std::get<ArgsIndex>(std::forward<ArgsTuple>(args))...);
42}
43
44template<typename C, typename MF, typename ArgsTuple, typename ArgsIndicies = std::make_index_sequence<std::tuple_size<ArgsTuple>::value>>
45void callMemberFunction(ArgsTuple&& args, C* object, MF function)
46{
47 callMemberFunctionImpl(object, function, std::forward<ArgsTuple>(args), ArgsIndicies());
48}
49
50// Dispatch functions with synchronous reply arguments.
51
52template <typename C, typename MF, typename CH, typename ArgsTuple, size_t... ArgsIndex>
53void callMemberFunctionImpl(C* object, MF function, CompletionHandler<CH>&& completionHandler, ArgsTuple&& args, std::index_sequence<ArgsIndex...>)
54{
55 (object->*function)(std::get<ArgsIndex>(std::forward<ArgsTuple>(args))..., WTFMove(completionHandler));
56}
57
58template<typename C, typename MF, typename CH, typename ArgsTuple, typename ArgsIndicies = std::make_index_sequence<std::tuple_size<ArgsTuple>::value>>
59void callMemberFunction(ArgsTuple&& args, CompletionHandler<CH>&& completionHandler, C* object, MF function)
60{
61 callMemberFunctionImpl(object, function, WTFMove(completionHandler), std::forward<ArgsTuple>(args), ArgsIndicies());
62}
63
64// Dispatch functions with connection parameter with synchronous reply arguments.
65
66template <typename C, typename MF, typename CH, typename ArgsTuple, size_t... ArgsIndex>
67void callMemberFunctionImpl(Connection& connection, C* object, MF function, CompletionHandler<CH>&& completionHandler, ArgsTuple&& args, std::index_sequence<ArgsIndex...>)
68{
69 (object->*function)(connection, std::get<ArgsIndex>(std::forward<ArgsTuple>(args))..., WTFMove(completionHandler));
70}
71
72template<typename C, typename MF, typename CH, typename ArgsTuple, typename ArgsIndicies = std::make_index_sequence<std::tuple_size<ArgsTuple>::value>>
73void callMemberFunction(Connection& connection, ArgsTuple&& args, CompletionHandler<CH>&& completionHandler, C* object, MF function)
74{
75 callMemberFunctionImpl(connection, object, function, WTFMove(completionHandler), std::forward<ArgsTuple>(args), ArgsIndicies());
76}
77
78// Dispatch functions with connection parameter with no reply arguments.
79
80template <typename C, typename MF, typename ArgsTuple, size_t... ArgsIndex>
81void callMemberFunctionImpl(C* object, MF function, Connection& connection, ArgsTuple&& args, std::index_sequence<ArgsIndex...>)
82{
83 (object->*function)(connection, std::get<ArgsIndex>(std::forward<ArgsTuple>(args))...);
84}
85
86template<typename C, typename MF, typename ArgsTuple, typename ArgsIndicies = std::make_index_sequence<std::tuple_size<ArgsTuple>::value>>
87void callMemberFunction(Connection& connection, ArgsTuple&& args, C* object, MF function)
88{
89 callMemberFunctionImpl(object, function, connection, std::forward<ArgsTuple>(args), ArgsIndicies());
90}
91
92// Main dispatch functions
93
94template<typename T>
95struct CodingType {
96 typedef std::remove_const_t<std::remove_reference_t<T>> Type;
97};
98
99class DataReference;
100class SharedBufferDataReference;
101template<> struct CodingType<const SharedBufferDataReference&> {
102 typedef DataReference Type;
103};
104
105template<typename... Ts>
106struct CodingType<std::tuple<Ts...>> {
107 typedef std::tuple<typename CodingType<Ts>::Type...> Type;
108};
109
110template<typename T, typename C, typename MF>
111void handleMessage(Decoder& decoder, C* object, MF function)
112{
113 Optional<typename CodingType<typename T::Arguments>::Type> arguments;
114 decoder >> arguments;
115 if (!arguments) {
116 ASSERT(decoder.isInvalid());
117 return;
118 }
119
120 callMemberFunction(WTFMove(*arguments), object, function);
121}
122
123template<typename T, typename C, typename MF>
124void handleMessage(Connection& connection, Decoder& decoder, C* object, MF function)
125{
126 Optional<typename CodingType<typename T::Arguments>::Type> arguments;
127 decoder >> arguments;
128 if (!arguments) {
129 ASSERT(decoder.isInvalid());
130 return;
131 }
132 callMemberFunction(connection, WTFMove(*arguments), object, function);
133}
134
135template<typename T, typename C, typename MF>
136void handleMessageSynchronous(Connection& connection, Decoder& decoder, std::unique_ptr<Encoder>& replyEncoder, C* object, MF function)
137{
138 Optional<typename CodingType<typename T::Arguments>::Type> arguments;
139 decoder >> arguments;
140 if (!arguments) {
141 ASSERT(decoder.isInvalid());
142 return;
143 }
144
145 typename T::DelayedReply completionHandler = [replyEncoder = WTFMove(replyEncoder), connection = makeRef(connection)] (auto&&... args) mutable {
146 T::send(WTFMove(replyEncoder), WTFMove(connection), args...);
147 };
148 callMemberFunction(WTFMove(*arguments), WTFMove(completionHandler), object, function);
149}
150
151template<typename T, typename C, typename MF>
152void handleMessageSynchronousWantsConnection(Connection& connection, Decoder& decoder, std::unique_ptr<Encoder>& replyEncoder, C* object, MF function)
153{
154 Optional<typename CodingType<typename T::Arguments>::Type> arguments;
155 decoder >> arguments;
156 if (!arguments) {
157 ASSERT(decoder.isInvalid());
158 return;
159 }
160
161 typename T::DelayedReply completionHandler = [replyEncoder = WTFMove(replyEncoder), connection = makeRef(connection)] (auto&&... args) mutable {
162 T::send(WTFMove(replyEncoder), WTFMove(connection), args...);
163 };
164 callMemberFunction(connection, WTFMove(*arguments), WTFMove(completionHandler), object, function);
165}
166
167template<typename T, typename C, typename MF>
168void handleMessageAsync(Connection& connection, Decoder& decoder, C* object, MF function)
169{
170 Optional<uint64_t> listenerID;
171 decoder >> listenerID;
172 if (!listenerID) {
173 ASSERT(decoder.isInvalid());
174 return;
175 }
176
177 Optional<typename CodingType<typename T::Arguments>::Type> arguments;
178 decoder >> arguments;
179 if (!arguments) {
180 ASSERT(decoder.isInvalid());
181 return;
182 }
183
184 typename T::AsyncReply completionHandler = [listenerID = *listenerID, connection = makeRef(connection)] (auto&&... args) mutable {
185 auto encoder = std::make_unique<Encoder>("AsyncReply", T::asyncMessageReplyName(), 0);
186 *encoder << listenerID;
187 T::send(WTFMove(encoder), WTFMove(connection), args...);
188 };
189 callMemberFunction(WTFMove(*arguments), WTFMove(completionHandler), object, function);
190}
191
192} // namespace IPC
193