1
/*
2
* \brief Support for performing RPC calls
3
* \author Norman Feske
4
* \date 2011-04-06
5
*/
6
7
/*
8
* Copyright (C) 2011-2013 Genode Labs GmbH
9
*
10
* This file is part of the Genode OS framework, which is distributed
11
* under the terms of the GNU General Public License version 2.
12
*/
13
14
#
ifndef _INCLUDE__BASE__RPC_CLIENT_H_
15
#
define _INCLUDE__BASE__RPC_CLIENT_H_
16
17
#
include <base/ipc.h>
18
#
include <base/trace/events.h>
19
20
namespace
Genode {
21
22
template
<
typename
>
struct
Rpc_client;
23
24
/**
25
* Count capabilities of a RPC_FUNCTION which are out parameters.
26
*/
27
template
<
typename
T
>
struct
Cap_para_out {
enum
{
Value =
0
}
;
}
;
28
template
<
typename
T
>
struct
Cap_para_out<
Capability<
T
>
*
>
{
enum
{
Value =
1
}
;
}
;
29
template
<
typename
T
>
struct
Cap_para_out<
Capability<
T
>
&
>
{
enum
{
Value =
1
}
;
}
;
30
template
<
>
struct
Cap_para_out<
Native_capability *
>
{
enum
{
Value =
1
}
;
}
;
31
template
<
>
struct
Cap_para_out<
Native_capability &
>
{
enum
{
Value =
1
}
;
}
;
32
33
template
<
typename
T
>
struct
Cap_return {
enum
{
Value =
0
}
;
}
;
34
template
<
typename
T
>
struct
Cap_return<
Capability<
T
>
>
{
enum
{
Value =
1
}
;
}
;
35
template
<
typename
T
>
struct
Cap_return<
Capability<
T
>
*
>
{
enum
{
Value =
1
}
;
}
;
36
template
<
typename
T
>
struct
Cap_return<
Capability<
T
>
&
>
{
enum
{
Value =
1
}
;
}
;
37
template
<
>
struct
Cap_return<
Native_capability
>
{
enum
{
Value =
1
}
;
}
;
38
template
<
>
struct
Cap_return<
Native_capability *
>
{
enum
{
Value =
1
}
;
}
;
39
template
<
>
struct
Cap_return<
Native_capability &
>
{
enum
{
Value =
1
}
;
}
;
40
41
template
<
typename
ARGS
>
42
struct
Rpc_caps_out {
43
enum
{
Value =
Cap_para_out<
typename
ARGS::
Head
>
::
Value
44
+
Rpc_caps_out<
typename
ARGS::
Tail
>
::
Value
}
;
}
;
45
46
template
<
>
47
struct
Rpc_caps_out<
Meta::
Empty
>
{
enum
{
Value =
0
}
;
}
;
48
49
template
<
typename
RPC_FUNCTION
>
50
struct
Rpc_function_caps_out {
51
enum
{
Value =
Rpc_caps_out<
typename
RPC_FUNCTION::
Server_args
>
::
Value +
52
Cap_return <
typename
RPC_FUNCTION::
Ret_type
>
::
Value
}
;
}
;
53
54
/***************************************************
55
** Implementation of `Capability:call` functions **
56
***************************************************/
57
58
template
<
typename
RPC_INTERFACE
>
59
template
<
typename
ATL
>
60
void
Capability<
RPC_INTERFACE
>
::
61
_marshal_args(
Ipc_client &
ipc_client
,
ATL &
args
)
const
62
{
63
if
(
Trait::
Rpc_direction<
typename
ATL::
Head
>
::
Type::
IN)
64
ipc_client <<
args.
get(
)
;
65
66
_marshal_args(
ipc_client,
args.
_2)
;
67
}
68
69
70
template
<
typename
RPC_INTERFACE
>
71
template
<
typename
T
>
72
void
Capability<
RPC_INTERFACE
>
::
73
_unmarshal_result(
Ipc_client &
ipc_client
,
T &
arg
,
74
Meta::
Overload_selector<
Rpc_arg_out
>
)
const
75
{
76
ipc_client >>
arg;
77
}
78
79
80
template
<
typename
RPC_INTERFACE
>
81
template
<
typename
T
>
82
void
Capability<
RPC_INTERFACE
>
::
83
_unmarshal_result(
Ipc_client &
ipc_client
,
T &
arg
,
84
Meta::
Overload_selector<
Rpc_arg_inout
>
)
const
85
{
86
_unmarshal_result(
ipc_client,
arg,
Meta::
Overload_selector<
Rpc_arg_out
>
(
)
)
;
87
}
88
89
90
template
<
typename
RPC_INTERFACE
>
91
template
<
typename
ATL
>
92
void
Capability<
RPC_INTERFACE
>
::
93
_unmarshal_results(
Ipc_client &
ipc_client
,
ATL &
args
)
const
94
{
95
/*
96
* Unmarshal current argument. The overload of
97
* `_unmarshal_result` is selected depending on the RPC
98
* direction.
99
*/
100
typedef
typename
Trait::
Rpc_direction<
typename
ATL::
Head
>
::
Type Rpc_dir;
101
_unmarshal_result(
ipc_client,
args.
get(
)
,
Meta::
Overload_selector<
Rpc_dir
>
(
)
)
;
102
103
/* unmarshal remaining arguments */
104
_unmarshal_results(
ipc_client,
args.
_2)
;
105
}
106
107
108
template
<
typename
RPC_INTERFACE
>
109
template
<
typename
IF
>
110
void
Capability<
RPC_INTERFACE
>
::
111
_call(
typename
IF::
Client_args &
args
,
typename
IF::
Ret_type &
ret
)
const
112
{
113
/**
114
* Message buffer for RPC message
115
*
116
* The message buffer gets automatically dimensioned according to the
117
* specified `IF` RPC function.
118
*/
119
enum
{
PROTOCOL_OVERHEAD =
4
*
sizeof
(
long)
,
120
CALL_MSG_SIZE =
Rpc_function_msg_size<
IF
,
RPC_CALL
>
::
Value
,
121
REPLY_MSG_SIZE =
Rpc_function_msg_size<
IF
,
RPC_REPLY
>
::
Value
,
122
CAP_BY_VALUE =
Rpc_function_caps_out<
IF
>
::
Value
}
;
123
124
Msgbuf<
CALL_MSG_SIZE +
PROTOCOL_OVERHEAD
>
call_buf;
125
Msgbuf<
REPLY_MSG_SIZE +
PROTOCOL_OVERHEAD
>
reply_buf;
126
127
Ipc_client
ipc_client(
*
this
,
&
call_buf
,
&
reply_buf
,
CAP_BY_VALUE
)
;
128
129
/* determine opcode of RPC function */
130
typedef
typename
RPC_INTERFACE::
Rpc_functions Rpc_functions;
131
Rpc_opcode opcode =
static_cast
<
int
>
(
Meta::
Index_of<
Rpc_functions
,
IF
>
::
Value)
;
132
133
/* marshal opcode and RPC input arguments */
134
ipc_client <<
opcode;
135
_marshal_args(
ipc_client,
args)
;
136
137
{
138
Trace::
Rpc_call
trace_event(
IF::
name(
)
,
call_buf
)
;
139
}
140
141
/* perform RPC, unmarshal return value */
142
ipc_client <<
IPC_CALL >>
ret;
143
144
{
145
Trace::
Rpc_returned
trace_event(
IF::
name(
)
,
reply_buf
)
;
146
}
147
148
/* unmarshal RPC output arguments */
149
_unmarshal_results(
ipc_client,
args)
;
150
151
/* reflect callee-side exception at the caller */
152
_check_for_exceptions(
ipc_client.
result(
)
,
153
Meta::
Overload_selector<
typename
IF::
Exceptions
>
(
)
)
;
154
}
155
}
156
157
158
/**
159
* RPC client
160
*
161
* This class template is the base class of the client-side implementation
162
* of the specified `RPC_INTERFACE`. Usually, it inherits the pure virtual
163
* functions declared in `RPC_INTERFACE` and has the built-in facility to
164
* perform RPC calls to this particular interface. Hence, the client-side
165
* implementation of each pure virtual interface function comes down to a
166
* simple wrapper in the line of `return call<Rpc_function>(arguments...)`.
167
*/
168
template
<
typename
RPC_INTERFACE
>
169
struct
Genode::
Rpc_client :
Capability<
RPC_INTERFACE
>
,
RPC_INTERFACE
170
{
171
typedef
RPC_INTERFACE Rpc_interface
;
172
173
Rpc_client(
Capability<
RPC_INTERFACE
>
const
&
cap
)
174
:
Capability<
RPC_INTERFACE
>
(
cap)
{
}
175
}
;
176
177
178
#
endif /* _INCLUDE__BASE__RPC_CLIENT_H_ */