2 * Copyright (c) 2009, Sun Microsystems, Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * - Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * - Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12 * - Neither the name of Sun Microsystems, Inc. nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
32 * Copyright (C) 1984, Sun Microsystems, Inc.
34 * Memory based rpc for simple testing and timing.
35 * Interface to create an rpc client and server in the same process.
36 * This lets us similate rpc and get round trip overhead, without
37 * any interference from the kernel.
40 //#include <pthread.h>
41 #include <reentrant.h>
50 extern mutex_t clntraw_lock
;
52 #define MCALL_MSG_SIZE 24
55 * This is the "network" we will be moving stuff over.
57 static struct clntraw_private
{
62 struct rpc_msg mashl_rpcmsg
;
63 char mashl_callmsg
[MCALL_MSG_SIZE
];
68 static enum clnt_stat
clnt_raw_call(CLIENT
*, rpcproc_t
, xdrproc_t
, void *,
69 xdrproc_t
, void *, struct timeval
);
70 static void clnt_raw_geterr(CLIENT
*, struct rpc_err
*);
71 static bool_t
clnt_raw_freeres(CLIENT
*, xdrproc_t
, void *);
72 static void clnt_raw_abort(CLIENT
*);
73 static bool_t
clnt_raw_control(CLIENT
*, u_int
, void *);
74 static void clnt_raw_destroy(CLIENT
*);
75 static struct clnt_ops
*clnt_raw_ops(void);
78 * Create a client handle for memory based rpc.
81 clnt_raw_create(prog
, vers
)
85 struct clntraw_private
*clp
;
86 struct rpc_msg call_msg
;
90 mutex_lock(&clntraw_lock
);
91 clp
= clntraw_private
;
93 clp
= (struct clntraw_private
*)calloc(1, sizeof (*clp
));
95 mutex_unlock(&clntraw_lock
);
98 if (__rpc_rawcombuf
== NULL
)
100 (char *)calloc(UDPMSGSIZE
, sizeof (char));
101 clp
->_raw_buf
= __rpc_rawcombuf
;
102 clntraw_private
= clp
;
104 xdrs
= &clp
->xdr_stream
;
105 client
= &clp
->client_object
;
107 * pre-serialize the static part of the call msg and stash it away
109 call_msg
.rm_direction
= CALL
;
110 call_msg
.rm_call
.cb_rpcvers
= RPC_MSG_VERSION
;
111 /* XXX: prog and vers have been long historically :-( */
112 call_msg
.rm_call
.cb_prog
= (u_int32_t
)prog
;
113 call_msg
.rm_call
.cb_vers
= (u_int32_t
)vers
;
114 xdrmem_create(xdrs
, clp
->u
.mashl_callmsg
, MCALL_MSG_SIZE
, XDR_ENCODE
);
115 if (! xdr_callhdr(xdrs
, &call_msg
))
116 //warnx("clntraw_create - Fatal header serialization error.");
117 clp
->mcnt
= XDR_GETPOS(xdrs
);
121 * Set xdrmem for client/server shared buffer
123 xdrmem_create(xdrs
, clp
->_raw_buf
, UDPMSGSIZE
, XDR_FREE
);
126 * create client handle
128 client
->cl_ops
= clnt_raw_ops();
129 client
->cl_auth
= authnone_create();
130 mutex_unlock(&clntraw_lock
);
135 static enum clnt_stat
136 clnt_raw_call(h
, proc
, xargs
, argsp
, xresults
, resultsp
, timeout
)
143 struct timeval timeout
;
145 struct clntraw_private
*clp
= clntraw_private
;
146 XDR
*xdrs
= &clp
->xdr_stream
;
148 enum clnt_stat status
;
149 struct rpc_err error
;
153 mutex_lock(&clntraw_lock
);
155 mutex_unlock(&clntraw_lock
);
158 mutex_unlock(&clntraw_lock
);
164 xdrs
->x_op
= XDR_ENCODE
;
166 clp
->u
.mashl_rpcmsg
.rm_xid
++ ;
167 if ((! XDR_PUTBYTES(xdrs
, clp
->u
.mashl_callmsg
, clp
->mcnt
)) ||
168 (! XDR_PUTINT32(xdrs
, (int32_t *)&proc
)) ||
169 (! AUTH_MARSHALL(h
->cl_auth
, xdrs
, NULL
)) ||
170 (! (*xargs
)(xdrs
, argsp
))) {
171 return (RPC_CANTENCODEARGS
);
173 (void)XDR_GETPOS(xdrs
); /* called just to cause overhead */
176 * We have to call server input routine here because this is
177 * all going on in one process. Yuk.
179 svc_getreq_common(FD_SETSIZE
);
184 xdrs
->x_op
= XDR_DECODE
;
186 msg
.acpted_rply
.ar_verf
= _null_auth
;
187 msg
.acpted_rply
.ar_results
.where
= resultsp
;
188 msg
.acpted_rply
.ar_results
.proc
= xresults
;
189 if (! xdr_replymsg(xdrs
, &msg
)) {
191 * It's possible for xdr_replymsg() to fail partway
192 * through its attempt to decode the result from the
193 * server. If this happens, it will leave the reply
194 * structure partially populated with dynamically
195 * allocated memory. (This can happen if someone uses
196 * clntudp_bufcreate() to create a CLIENT handle and
197 * specifies a receive buffer size that is too small.)
198 * This memory must be free()ed to avoid a leak.
201 xdrs
->x_op
= XDR_FREE
;
202 xdr_replymsg(xdrs
, &msg
);
204 return (RPC_CANTDECODERES
);
206 _seterr_reply(&msg
, &error
);
207 status
= error
.re_status
;
209 if (status
== RPC_SUCCESS
) {
210 if (! AUTH_VALIDATE(h
->cl_auth
, &msg
.acpted_rply
.ar_verf
, 0)) {
211 status
= RPC_AUTHERROR
;
213 } /* end successful completion */
215 if (AUTH_REFRESH(h
->cl_auth
, &msg
))
217 } /* end of unsuccessful completion */
219 if (status
== RPC_SUCCESS
) {
220 if (! AUTH_VALIDATE(h
->cl_auth
, &msg
.acpted_rply
.ar_verf
, 0)) {
221 status
= RPC_AUTHERROR
;
223 if (msg
.acpted_rply
.ar_verf
.oa_base
!= NULL
) {
224 xdrs
->x_op
= XDR_FREE
;
225 (void)xdr_opaque_auth(xdrs
, &(msg
.acpted_rply
.ar_verf
));
234 clnt_raw_geterr(cl
, err
)
243 clnt_raw_freeres(cl
, xdr_res
, res_ptr
)
248 struct clntraw_private
*clp
= clntraw_private
;
249 XDR
*xdrs
= &clp
->xdr_stream
;
252 mutex_lock(&clntraw_lock
);
254 rval
= (bool_t
) RPC_FAILED
;
255 mutex_unlock(&clntraw_lock
);
258 mutex_unlock(&clntraw_lock
);
259 xdrs
->x_op
= XDR_FREE
;
260 return ((*xdr_res
)(xdrs
, res_ptr
));
272 clnt_raw_control(cl
, ui
, str
)
287 static struct clnt_ops
*
290 static struct clnt_ops ops
;
291 extern mutex_t ops_lock
;
293 /* VARIABLES PROTECTED BY ops_lock: ops */
295 mutex_lock(&ops_lock
);
296 if (ops
.cl_call
== NULL
) {
297 ops
.cl_call
= clnt_raw_call
;
298 ops
.cl_abort
= clnt_raw_abort
;
299 ops
.cl_geterr
= clnt_raw_geterr
;
300 ops
.cl_freeres
= clnt_raw_freeres
;
301 ops
.cl_destroy
= clnt_raw_destroy
;
302 ops
.cl_control
= clnt_raw_control
;
304 mutex_unlock(&ops_lock
);