2 * Copyright 2008, Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #ifndef NATIVE_CLIENT_TOOLS_LIBSRPC_NACL_SRPC_H_
34 #define NATIVE_CLIENT_TOOLS_LIBSRPC_NACL_SRPC_H_
38 * Defines the Simple RPC (SRPC) API for Native Client applications and for
39 * trusted clients communicating using SRPC.
48 * TODO break this file into separate files for sdk and service_runtime
51 #ifdef __native_client__
53 # include <sys/types.h>
54 # include <sys/nacl_imc_api.h>
57 * Avoid emacs' penchant for auto-indenting extern "C" blocks.
60 # define EXTERN_C_BEGIN extern "C" {
61 # define EXTERN_C_END }
63 # define EXTERN_C_BEGIN
65 # endif /* __cplusplus */
67 * Contains a file descriptor for use as an IMC channel.
69 typedef int NaClSrpcImcDescType
;
71 # include "native_client/include/portability.h"
72 # include "native_client/include/nacl_base.h"
73 # include "native_client/service_runtime/nacl_log.h"
74 # include "native_client/service_runtime/nrd_xfer_lib/nrd_all_modules.h"
75 # include "native_client/service_runtime/nrd_xfer_lib/nrd_xfer.h"
76 # include "native_client/service_runtime/nrd_xfer_lib/nrd_xfer_effector.h"
77 # include "native_client/intermodule_comm/nacl_imc_c.h"
79 * In trusted code we use a NaClDesc to describe the IMC channel.
80 * It is this difference between trusted and untrusted code that motivated
81 * creating a type name.
83 typedef struct NaClDesc
* NaClSrpcImcDescType
;
90 * Result codes to be returned from Simple RPC services.
92 typedef enum NaClSrpcResultCodes
{
93 /** Invocation was successful. */
94 NACL_SRPC_RESULT_OK
= 256,
95 /** Invocation was successful, exit the server dispatch loop.
96 * When returned from an RPC method, this causes the server to return
97 * NACL_SRPC_RESULT_OK and then exit the receive-dispatch-reply loop.
99 NACL_SRPC_RESULT_BREAK
,
100 /** Some or all of a message was not received. */
101 NACL_SRPC_RESULT_MESSAGE_TRUNCATED
,
102 /** The SRPC runtime system ran out of memory. */
103 NACL_SRPC_RESULT_NO_MEMORY
,
104 /** The SRPC message layer detected a protocol version difference. */
105 NACL_SRPC_RESULT_PROTOCOL_MISMATCH
,
106 /** The RPC number was not valid for any method. */
107 NACL_SRPC_RESULT_BAD_RPC_NUMBER
,
108 /** An unknown type was passed to or returned from an RPC. */
109 NACL_SRPC_RESULT_BAD_ARG_TYPE
,
110 /** Too few arguments were passed to or returned from an RPC. */
111 NACL_SRPC_RESULT_TOO_FEW_ARGS
,
112 /** Too many arguments were passed to or returned from an RPC. */
113 NACL_SRPC_RESULT_TOO_MANY_ARGS
,
114 /** One or more input argument types did not match the expected types. */
115 NACL_SRPC_RESULT_IN_ARG_TYPE_MISMATCH
,
116 /** One or more output argument types did not match the expected types. */
117 NACL_SRPC_RESULT_OUT_ARG_TYPE_MISMATCH
,
118 /** An unknown SRPC internal error occurred. */
119 NACL_SRPC_RESULT_INTERNAL
,
120 /** The application signalled a generic error. */
121 NACL_SRPC_RESULT_APP_ERROR
125 * Returns a descriptive string for the specified NaClSrpcError value.
126 * @param error_val A NaClSrpcError to be translated to a string.
127 * @return If error_val is valid, returns a string. Otherwise returns the
128 * string "Unrecognized NaClSrpcError value"
130 extern char* NaClSrpcErrorString(NaClSrpcError error_val
);
133 * Type tag values for NaClSrpcArg unions.
135 enum NaClSrpcArgType
{
136 NACL_SRPC_ARG_TYPE_INVALID
= 'X', /**< invalid type */
137 NACL_SRPC_ARG_TYPE_BOOL
= 'b', /**< scalar bool */
138 NACL_SRPC_ARG_TYPE_CHAR_ARRAY
= 'C', /**< array of char */
139 NACL_SRPC_ARG_TYPE_DOUBLE
= 'd', /**< scalar double */
140 NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY
= 'D', /**< array of double */
141 NACL_SRPC_ARG_TYPE_HANDLE
= 'h', /**< a descriptor (handle) */
142 NACL_SRPC_ARG_TYPE_INT
= 'i', /**< scalar int */
143 NACL_SRPC_ARG_TYPE_INT_ARRAY
= 'I', /**< array of int*/
144 NACL_SRPC_ARG_TYPE_STRING
= 's', /**< NUL-terminated string */
145 NACL_SRPC_ARG_TYPE_OBJECT
= 'o', /**< scriptable object*/
146 NACL_SRPC_ARG_TYPE_VARIANT_ARRAY
= 'A' /**< array of NaClSrpcArg structs */
149 struct NaClSrpcVariantArray
{
151 struct NaClSrpcArg
*varr
;
155 * Argument data type for passing arrays of char.
158 struct NaClSrpcCharArray
{
159 uint32_t count
; /**< The number of characters in the array */
160 char *carr
; /**< A chunk of memory containing "count" characters */
164 * Argument data type for passing arrays of int.
167 struct NaClSrpcIntArray
{
168 uint32_t count
; /**< The number of integers in the array */
169 int *iarr
; /**< A chunk of memory containing "count" integers */
173 * Argument data type for passing arrays of double.
176 struct NaClSrpcDoubleArray
{
177 uint32_t count
; /**< The number of doubles in the array */
178 double *darr
; /**< A chunk of memory containing "count" doubles */
182 * Used to convey parameters to and from RPC invocations. It is a variant
183 * type, with tag telling whether to treat the parameter as a bool or an
184 * array of characters, etc.
187 namespace nacl_srpc
{
188 class ScriptableHandleBase
;
193 enum NaClSrpcArgType tag
;
194 uint32_t reserved_pad
;
196 * For efficiency, doubles should be 8-byte aligned so that
197 * loading them would require a single bus cycle, and arrays of
198 * NaClSrpcArgs will have to be 8-byte aligned as well, so it's
199 * either a 4 byte padding between the tag and the union or
200 * (implicitly) at the end. gcc does not (by default) enforce
201 * 8-byte alignment but visual studio does, so we explicitly pad
202 * so that both compilers will use the same memory layout, even if
203 * the gcc -malign-double flag were omitted.
209 struct NaClSrpcCharArray caval
;
210 struct NaClSrpcIntArray iaval
;
211 struct NaClSrpcDoubleArray daval
;
213 NaClSrpcImcDescType hval
;
214 /* object value that can be exported to the browser as is */
215 /* TODO - try to use a single type here */
217 nacl_srpc::ScriptableHandleBase
*oval
;
221 struct NaClSrpcVariantArray vaval
;
225 typedef struct NaClSrpcArg NaClSrpcArg
;
228 /* TODO - duplicate string? */
229 #define STRINGZ_TO_SRPCARG(val, arg) do { \
230 (arg).tag = NACL_SRPC_ARG_TYPE_STRING; \
231 (arg).u.sval = (val); } while(0)
234 * The maximum number of arguments per SRPC routine.
236 #define NACL_SRPC_MAX_ARGS 128
239 * The maximum number of characters returnable from service discovery.
241 #define NACL_SRPC_MAX_SERVICE_DISCOVERY_CHARS 4000
243 /* A pointer to an SRPC channel data structure. */
244 typedef struct NaClSrpcChannel
*NaClSrpcChannelPtr
;
247 * Binaries that implement SRPC methods (servers) describe their services
248 * using these structures. These are converted into NaClSrpcDescs by the
249 * server constructor. They are also used when service discovery is done.
251 struct NaClSrpcHandlerDesc
{
252 char const *entry_fmt
; /**< a string containing
253 "name:input_types:output_types" */
254 int (*handler
)(NaClSrpcChannelPtr channel
,
255 NaClSrpcArg
**in_args
,
256 NaClSrpcArg
**out_args
); /**< function pointer
257 used to process calls
258 to the named method */
261 typedef struct NaClSrpcHandlerDesc NaClSrpcHandlerDesc
;
265 * Used by clients to retain method name and type information.
267 struct NaClSrpcDesc
{
268 char const *rpc_name
; /**< string containing the method name*/
269 char const *in_args
; /**< string containing the method input types */
270 char const *out_args
; /**< string containing the method output types */
271 int (*handler
)(NaClSrpcChannelPtr channel
,
272 NaClSrpcArg
**in_args
,
273 NaClSrpcArg
**out_args
); /**< function pointer
274 used to process calls
275 to the named method */
278 typedef struct NaClSrpcDesc NaClSrpcDesc
;
282 * The structure used to provide a buffering layer over the IMC.
284 struct NaClSrpcImcBuffer
{
285 struct NaClImcMsgIoVec iovec
[1]; /**< IMC message descriptor */
286 #ifdef __native_client__
287 struct NaClImcMsgHdr header
; /**< IMC message header */
288 unsigned char bytes
[IMC_USER_BYTES_MAX
]; /**< character array
292 NaClSrpcImcDescType descs
[IMC_USER_DESC_MAX
]; /**< array of
297 struct NaClImcTypedMsgHdr header
;
298 unsigned char bytes
[NACL_ABI_IMC_USER_BYTES_MAX
];
299 NaClSrpcImcDescType descs
[NACL_ABI_IMC_USER_DESC_MAX
];
301 uint32_t next_desc
; /**< index into "bytes" of the next
302 descriptor to be read or written */
303 size_t next_byte
; /**< index into "bytes" of the next
304 data byte to be read or written */
305 size_t last_byte
; /**< index into "bytes" of the last
306 data byte to be read or written */
310 * A typedef for struct NaClSrpcImcBuffer for use in C.
312 typedef struct NaClSrpcImcBuffer NaClSrpcImcBuffer
;
316 * The encapsulation of all the data necessary for an RPC connection,
317 * either client or server.
319 struct NaClSrpcChannel
{
320 NaClSrpcImcDescType imc_handle
;
321 #ifndef __native_client__
322 struct NaClNrdXferEffector eff
;
324 NaClSrpcImcBuffer send_buf
;
325 NaClSrpcImcBuffer receive_buf
;
326 NaClSrpcDesc
* rpc_descr
;
328 void *server_instance_data
;
329 const char* service_string
;
330 size_t service_string_length
;
334 double imc_read_usec
;
335 double imc_write_usec
;
339 * A typedef for struct NaClSrpcChannel for use in C.
341 typedef struct NaClSrpcChannel NaClSrpcChannel
;
345 * Constructs an SRPC client object communicating over an IMC descriptor.
346 * Clients issue RPC requests and receive responses.
347 * @param channel The channel descriptor to be constructed.
348 * @param imc_desc The NaClSrpcImcDescType describing the IMC channel to
350 * @return On success, 1; on failure, 0.
352 int NaClSrpcClientCtor(NaClSrpcChannel
*channel
, NaClSrpcImcDescType imc_desc
);
354 * Constructs an SRPC server object communicating over an IMC descriptor.
355 * Servers wait for RPC requests, dispatch them to implementations, and return
357 * @param channel The channel descriptor to be constructed.
358 * @param imc_desc The NaClSrpcImcDescType describing the IMC channel to
360 * @param handlers An array of NaClSrpcHandlerDesc structures describing the
361 * set of services handled by this server.
362 * @param instance_data A value to be stored on the channel descriptor
363 * for conveying data specific to this particular server instance.
364 * @return On success, 1; on failure, 0.
366 int NaClSrpcServerCtor(NaClSrpcChannel
*channel
,
367 NaClSrpcImcDescType imc_desc
,
368 const NaClSrpcHandlerDesc
*handlers
,
369 void* instance_data
);
371 * A utility function that creates a NaClSrpcImcDescType from the
372 * platform-defined NaClHandle type.
373 * @param handle The handle to be converted.
374 * @return On success, a valid NaClSrpcImcDescType. On failure, -1.
376 NaClSrpcImcDescType
NaClSrpcImcDescTypeFromHandle(NaClHandle handle
);
379 * Destroys the specified client or server channel.
380 * @param channel The channel to be destroyed.
382 void NaClSrpcDtor(NaClSrpcChannel
*channel
);
385 * Runs an SRPC receive-dispatch-respond loop on the specified socket
387 * @param socket_desc A NaClHandle that RPCs will communicate over.
388 * @param methods An array of NaClSrpcHandlerDesc structures describing the
389 * set of services handled by this server.
390 * @param instance_data A value to be stored on the channel descriptor
391 * for conveying data specific to this particular server instance.
392 * @return On success, 1; on failure, 0.
394 int NaClSrpcServerLoop(NaClHandle socket_desc
,
395 const struct NaClSrpcHandlerDesc methods
[],
396 void *instance_data
);
399 * Runs an SRPC receive-dispatch-respond loop on the specified
400 * NaClSrpcImcDescType object.
401 * @param imc_socket_desc A NaClSrpcImcDescType object that RPCs will
403 * @param methods An array of NaClSrpcHandlerDesc structures
404 * describing the set of services handled by this server.
405 * @param instance_data A value to be stored on the channel
406 * descriptor for conveying data specific to this particular server
408 * @return On success, 1; on failure, 0.
410 int NaClSrpcServerLoopImcDesc(NaClSrpcImcDescType imc_socket_desc
,
411 const struct NaClSrpcHandlerDesc methods
[],
412 void *instance_data
);
414 #ifdef __native_client__
416 * Runs an SRPC receive-dispatch-respond loop on the "default" descriptor.
417 * NaCl modules are started with a default descriptor (obtained by an accept
418 * call on the bound socket created by the service runtime). The methods
419 * exported are those using the NACL_SRPC_METHOD macro in the source of the
420 * module, plus the implicitly defined methods.
421 * @param instance_data A value to be stored on the channel descriptor
422 * for conveying data specific to this particular server instance.
423 * @return On success, 1; on failure, 0.
425 int NaClSrpcDefaultServerLoop(void *instance_data
);
426 #endif /* __native_client__ */
429 * Prints the methods available from the specified channel to stdout. For
430 * services, the method list is the table specified when the
431 * NaClSrpcServerCtor was invoked. For clients, it is set by the initial
432 * call to the implicit service_discovery method.
433 * @param channel A channel descriptor.
435 void NaClSrpcDumpInterfaceDesc(const NaClSrpcChannel
*channel
);
437 * Obtains the index of the specified RPC name.
438 * @param channel The channel descriptor to be searched.
439 * @param name The exported name of the method.
440 * @return A non-negative index if the name was found in the channel's set of
441 * methods. If the name was not found, it returns -1.
443 int NaClSrpcGetRpcNum(const NaClSrpcChannel
*channel
, char const *name
);
445 #ifdef __native_client__
447 * Not documented: in Native Client code the default RPC descriptors are
448 * recorded in a special section, ".nacl_rpc_methods".
449 * The handler array begins at __kNaclSrpcHandlers.
451 extern const struct NaClSrpcHandlerDesc
452 __attribute__ ((section (".nacl_rpc_methods")))
453 __attribute__ ((aligned (8)))
454 __kNaClSrpcHandlers
[];
456 * Not documented: in NativeClient code the default RPC descriptors are
457 * recorded in a special section, ".nacl_rpc_methods".
458 * The handler array ends at __kNaclSrpcHandlerEnd.
460 extern const struct NaClSrpcHandlerDesc
461 __attribute__ ((section (".nacl_rpc_methods")))
462 __attribute__ ((aligned (8)))
463 __kNaClSrpcHandlerEnd
;
465 * Exports a method to the default RPC descriptor array.
466 * @param entry_format a string with the format "x:y:z", where x is the method
467 * name, * y is the parameter type list, and z is the return value type list.
468 * @param method_handler A function pointer for the implementation of the
471 #define NACL_SRPC_METHOD(entry_format, method_handler) \
472 struct NaClSrpcHandlerDesc \
473 __attribute__ ((section (".nacl_rpc_methods"))) \
474 __attribute__ ((aligned (8))) \
475 NaClSrpcMethod##method_handler = \
476 { entry_format, method_handler }
478 #endif /* defined(NACL_LINUX) ... */
481 * @clientSrpc Invokes a specified RPC on the given channel. Parameters
482 * are passed by stdarg conventions and determined from the types specified
483 * in the method tables.
484 * @param channel The channel descriptor to use to invoke the RPC.
485 * @param rpc_name The name of the RPC to be invoked.
486 * @return A NaClSrpcResultCodes indicating success (NACL_SRPC_RESULT_OK)
488 * @see NaClSrpcResultCodes
490 extern NaClSrpcError
NaClSrpcInvokeByName(NaClSrpcChannel
*channel
,
491 const char *rpc_name
,
494 * @clientSrpc Invokes a specified RPC on the given channel. Parameters
495 * are passed by stdarg conventions and determined from the types specified
496 * in the method tables stored in channel.
497 * @param channel The channel descriptor to use to invoke the RPC.
498 * @param rpc_num The index of the RPC to be invoked.
499 * @return A NaClSrpcResultCodes indicating success (NACL_SRPC_RESULT_OK)
501 * @see NaClSrpcResultCodes
503 extern NaClSrpcError
NaClSrpcInvoke(NaClSrpcChannel
*channel
,
507 * @clientSrpc Invokes a specified RPC on the given channel. Parameters are
508 * passed in arrays and are type-checked against the types specified in the
509 * method tables stored in channel.
510 * @param channel The channel descriptor to use to invoke the RPC.
511 * @param rpc_num The index of the RPC to be invoked.
512 * @param args The array of parameter pointers to arguments to be passed in.
513 * @param rets The array of parameter pointers to arguments to be returned.
514 * @return A NaClSrpcResultCodes indicating success (NACL_SRPC_RESULT_OK)
516 * @see NaClSrpcResultCodes
518 extern NaClSrpcError
NaClSrpcInvokeV(NaClSrpcChannel
*channel
,
521 NaClSrpcArg
*rets
[]);
523 * @clientSrpc Invokes a specified RPC on the given channel. Parameters are
524 * passed in and returned through pointers to stdargs. They are type-checked
525 * against the types specified in the method tables stored in channel.
526 * @param channel The channel descriptor to use to invoke the RPC.
527 * @param rpc_num The index of the RPC to be invoked.
528 * @param in_va The pointer to stdargs list of arguments to be passed in.
529 * @param out_va The pointer to stdargs list of arguments to be returned.
530 * @return A NaClSrpcResultCodes indicating success (NACL_SRPC_RESULT_OK)
532 * @see NaClSrpcResultCodes
534 extern NaClSrpcError
NaClSrpcInvokeVaList(NaClSrpcChannel
*channel
,
540 * @serverSrpc Receives an RPC request, invokes the corresponding method
541 * from the table in the channel, and returns the result.
542 * @param channel The channel descriptor to use to invoke the RPC.
543 * @return A NaClSrpcResultCodes indicating success (NACL_SRPC_RESULT_OK)
545 * @see NaClSrpcResultCodes
547 NaClSrpcError
NaClSrpcReceiveAndDispatch(NaClSrpcChannel
*channel
);
550 * @eitherSrpc Enables or disables timing of the specified channel.
551 * @param channel The channel descriptor whose timing to consult.
552 * @param enable_timing If zero, disable timing. Otherwise, enable timing.
553 * @see NaClSrpcGetTimes()
555 void NaClSrpcToggleChannelTiming(NaClSrpcChannel
* channel
, int enable_timing
);
557 * @eitherSrpc Gathers the microsecond-granularity timing results retained
558 * for the specified channel. If timing is not enabled, this function sets
559 * all _time parameters to 0.0.
560 * @param channel A channel descriptor.
561 * @param send_time The time spent in sending via this channel.
562 * @param receive_time The time spent in receiving via this channel.
563 * @param imc_read_time The time spent waiting for IMC layer reads via
565 * @param imc_write_time The time spent waiting for IMC layer writes via
567 * @see NaclSrpcToggleChannelTiming()
569 void NaClSrpcGetTimes(NaClSrpcChannel
*channel
,
571 double *receive_time
,
572 double *imc_read_time
,
573 double *imc_write_time
);
576 * @serverSrpc Initializes the SRPC system, setting up the command channel
577 * and preparing the graphics subsystem for embedding in the browser.
582 * RPC number for "implicit" timing method.
584 #define NACL_SRPC_GET_TIMES_METHOD 0xfffffffe
586 * RPC number for "implicit" timing control method.
588 #define NACL_SRPC_TOGGLE_CHANNEL_TIMING_METHOD 0xfffffffd
594 * End of System Calls group
597 #endif /* NATIVE_CLIENT_TOOLS_LIBSRPC_NACL_SRPC_H_ */