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.
34 * NaCl service library. a primitive rpc library
37 #ifndef __native_client__
38 #include "native_client/include/portability.h"
39 #include "native_client/service_runtime/nacl_desc_imc.h"
41 #endif /* __native_client__ */
42 #if defined(__native_client__) || !defined(NACL_WINDOWS)
49 #include "nacl_srpc.h"
50 #include "nacl_srpc_internal.h"
54 * A utility function for copying strings needed for ServerCtor
56 static char* CopyStringLength(const char* string
, size_t length
) {
57 char* copy
= (char*) malloc(length
+ 1);
58 strncpy(copy
, string
, length
);
64 * Service discovery is used to build an interface description that
65 * is searched for rpc dispatches.
67 static int NaClSrpcBuildInterfaceDesc(NaClSrpcChannel
*channel
) {
69 NaClSrpcArg
* ins
[] = { NULL
};
70 NaClSrpcArg out_carray
;
71 NaClSrpcArg
* outs
[] = { &out_carray
, NULL
};
73 * We initialize the service descriptors to have service discovery
74 * and other default services (as they are added).
76 NaClSrpcDesc basic_services
[] = {
77 { "service_discovery", "", "C", NULL
},
79 channel
->rpc_descr
= basic_services
;
80 channel
->rpc_count
= sizeof(basic_services
) / sizeof(basic_services
[0]);
82 /* Build the argument value for invoking service discovery */
83 out_carray
.tag
= NACL_SRPC_ARG_TYPE_CHAR_ARRAY
;
84 out_carray
.u
.caval
.count
= NACL_SRPC_MAX_SERVICE_DISCOVERY_CHARS
;
85 out_carray
.u
.caval
.carr
= calloc(NACL_SRPC_MAX_SERVICE_DISCOVERY_CHARS
, 1);
86 if (NULL
== out_carray
.u
.caval
.carr
) {
87 fprintf(stderr
, "service_discovery could not allocate memory\n");
90 /* Invoke service discovery, getting description string */
91 errcode
= NaClSrpcInvokeV(channel
, 0, ins
, outs
);
92 if (NACL_SRPC_RESULT_OK
!= errcode
) {
93 fprintf(stderr
, "service_discovery call failed(%d): %s\n", errcode
,
94 NaClSrpcErrorString(errcode
));
97 /* Build the real rpc description from the resulting string. */
98 channel
->rpc_descr
= __NaClSrpcBuildSrpcDesc(outs
[0]->u
.caval
.carr
,
100 /* Free the service string */
101 free(out_carray
.u
.caval
.carr
);
107 * The constructors and destructor.
111 * Set up the buffering structures for a channel.
113 int NaClSrpcClientCtor(NaClSrpcChannel
* channel
, NaClSrpcImcDescType handle
) {
114 channel
->imc_handle
= handle
;
116 #ifndef __native_client__
117 if (channel
->imc_handle
== NULL
) {
120 if (!NaClNrdXferEffectorCtor(&channel
->eff
, channel
->imc_handle
)) {
124 /* Construct the buffers. */
125 __NaClSrpcImcBufferCtor(&channel
->send_buf
, 1);
126 __NaClSrpcImcBufferCtor(&channel
->receive_buf
, 0);
127 /* Disable timing and initialize the timing counters. */
128 channel
->timing_enabled
= 0;
129 channel
->send_usec
= 0.0;
130 channel
->receive_usec
= 0.0;
131 channel
->imc_read_usec
= 0.0;
132 channel
->imc_write_usec
= 0.0;
133 /* Do service discovery to speed method invocation. */
134 if (NaClSrpcBuildInterfaceDesc(channel
) == 0) {
137 /* Return success. */
141 int NaClSrpcServerCtor(NaClSrpcChannel
* channel
,
142 NaClSrpcImcDescType handle
,
143 const NaClSrpcHandlerDesc
* handlers
,
144 void* channel_instance_data
) {
145 uint32_t handler_count
;
148 channel
->imc_handle
= handle
;
149 #ifndef __native_client__
150 if (channel
->imc_handle
== NULL
) {
153 if (!NaClNrdXferEffectorCtor(&channel
->eff
, channel
->imc_handle
)) {
157 /* Construct the buffers. */
158 __NaClSrpcImcBufferCtor(&channel
->send_buf
, 1);
159 __NaClSrpcImcBufferCtor(&channel
->receive_buf
, 0);
160 /* Count the number of methods. */
162 while (NULL
!= handlers
[handler_count
].entry_fmt
)
165 * This is a server connection, build the descriptors by parsing the
166 * handler descriptors passed in.
169 (NaClSrpcDesc
*) malloc(handler_count
* sizeof(*channel
->rpc_descr
));
170 channel
->rpc_count
= handler_count
;
171 for (i
= 0; i
< handler_count
; ++i
) {
175 /* entry_fmt should look like "name:inargs:outargs" */
176 p
= handlers
[i
].entry_fmt
;
178 nextp
= strchr(p
, ':');
182 channel
->rpc_descr
[i
].rpc_name
= CopyStringLength(p
, nextp
- p
);
185 nextp
= strchr(p
, ':');
189 channel
->rpc_descr
[i
].in_args
= CopyStringLength(p
, nextp
- p
);
192 nextp
= strchr(p
, '\0');
196 channel
->rpc_descr
[i
].out_args
= CopyStringLength(p
, nextp
- p
);
197 /* Add the handler pointer to the descriptor. */
198 channel
->rpc_descr
[i
].handler
= handlers
[i
].handler
;
200 /* Disable timing and initialize the timing counters. */
201 channel
->timing_enabled
= 0;
202 channel
->send_usec
= 0.0;
203 channel
->receive_usec
= 0.0;
204 channel
->imc_read_usec
= 0.0;
205 channel
->imc_write_usec
= 0.0;
206 /* Return success. */
210 void NaClSrpcDtor(NaClSrpcChannel
*channel
) {
211 #ifndef __native_client__
212 struct NaClDescEffector
* effp
= (struct NaClDescEffector
*) &channel
->eff
;
213 effp
->vtbl
->Dtor(effp
);
214 NaClDescUnref(channel
->imc_handle
);
216 if (channel
->rpc_descr
)
217 free(channel
->rpc_descr
);