ncval-annotate: Include function names and inlining context
[nativeclient.git] / tools / libsrpc / nacl_srpc.c
blob990d3c7ffc26a929ca3ddda1d1eae263dee844d9
1 /*
2 * Copyright 2008, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
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
14 * distribution.
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)
43 #include <unistd.h>
44 #endif
45 #include <stdarg.h>
46 #include <stdlib.h>
47 #include <string.h>
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);
59 copy[length] = '\0';
60 return copy;
64 * Service discovery is used to build an interface description that
65 * is searched for rpc dispatches.
67 static int NaClSrpcBuildInterfaceDesc(NaClSrpcChannel *channel) {
68 int errcode;
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");
88 return 0;
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));
95 return 0;
97 /* Build the real rpc description from the resulting string. */
98 channel->rpc_descr = __NaClSrpcBuildSrpcDesc(outs[0]->u.caval.carr,
99 &channel->rpc_count);
100 /* Free the service string */
101 free(out_carray.u.caval.carr);
102 /* Return success */
103 return 1;
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) {
118 return 0;
120 if (!NaClNrdXferEffectorCtor(&channel->eff, channel->imc_handle)) {
121 return 0;
123 #endif
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) {
135 return 0;
137 /* Return success. */
138 return 1;
141 int NaClSrpcServerCtor(NaClSrpcChannel* channel,
142 NaClSrpcImcDescType handle,
143 const NaClSrpcHandlerDesc* handlers,
144 void* channel_instance_data) {
145 uint32_t handler_count;
146 uint32_t i;
148 channel->imc_handle = handle;
149 #ifndef __native_client__
150 if (channel->imc_handle == NULL) {
151 return 0;
153 if (!NaClNrdXferEffectorCtor(&channel->eff, channel->imc_handle)) {
154 return 0;
156 #endif
157 /* Construct the buffers. */
158 __NaClSrpcImcBufferCtor(&channel->send_buf, 1);
159 __NaClSrpcImcBufferCtor(&channel->receive_buf, 0);
160 /* Count the number of methods. */
161 handler_count = 0;
162 while (NULL != handlers[handler_count].entry_fmt)
163 ++handler_count;
165 * This is a server connection, build the descriptors by parsing the
166 * handler descriptors passed in.
168 channel->rpc_descr =
169 (NaClSrpcDesc*) malloc(handler_count * sizeof(*channel->rpc_descr));
170 channel->rpc_count = handler_count;
171 for (i = 0; i < handler_count; ++i) {
172 const char* p;
173 const char* nextp;
175 /* entry_fmt should look like "name:inargs:outargs" */
176 p = handlers[i].entry_fmt;
177 /* Get name. */
178 nextp = strchr(p, ':');
179 if (p == NULL) {
180 return 0;
182 channel->rpc_descr[i].rpc_name = CopyStringLength(p, nextp - p);
183 p = nextp + 1;
184 /* Get inargs. */
185 nextp = strchr(p, ':');
186 if (p == NULL) {
187 return 0;
189 channel->rpc_descr[i].in_args = CopyStringLength(p, nextp - p);
190 p = nextp + 1;
191 /* Get outargs. */
192 nextp = strchr(p, '\0');
193 if (p == NULL) {
194 return 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. */
207 return 1;
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);
215 #endif
216 if (channel->rpc_descr)
217 free(channel->rpc_descr);