1 : /*
2 : * Copyright (c) 2011 The Native Client Authors. All rights reserved.
3 : * Use of this source code is governed by a BSD-style license that can be
4 : * found in the LICENSE file.
5 : */
6 :
7 : /*
8 : * NaCl service library. a primitive rpc library
9 : */
10 :
11 : #include <stdarg.h>
12 : #include <stdlib.h>
13 : #include <string.h>
14 :
15 : #ifndef __native_client__
16 : #include "native_client/src/include/portability.h"
17 : #include "native_client/src/trusted/desc/nacl_desc_imc.h"
18 : #endif /* __native_client__ */
19 : #include "native_client/src/shared/srpc/nacl_srpc.h"
20 : #include "native_client/src/shared/platform/nacl_check.h"
21 : #include "native_client/src/shared/srpc/nacl_srpc_internal.h"
22 : #include "native_client/src/shared/srpc/nacl_srpc_message.h"
23 :
24 : /*
25 : * Service discovery is used to build an interface description that
26 : * is searched for rpc dispatches.
27 : */
28 2 : static NaClSrpcService* BuildClientService(NaClSrpcChannel* channel) {
29 2 : NaClSrpcArg* ins[] = { NULL };
30 : NaClSrpcArg out_carray;
31 : NaClSrpcArg* outs[2];
32 2 : NaClSrpcService* tmp_service = NULL;
33 2 : NaClSrpcService* service = NULL;
34 2 : NaClSrpcHandlerDesc basic_services[] = { { NULL, NULL } };
35 : NaClSrpcError service_discovery_result;
36 2 : NaClSrpcService* returned_service = NULL;
37 :
38 : /*
39 : * Service discovery requires a temporary setting of channel->client.
40 : * To ensure that this does not clobber a previous setting, enforce
41 : * a precondition that it is NULL beforehand.
42 : */
43 2 : CHECK(NULL == channel->client);
44 : /* Set up the output parameters for service discovery. */
45 2 : NaClSrpcArgCtor(&out_carray);
46 2 : outs[0] = &out_carray;
47 2 : outs[1] = NULL;
48 2 : out_carray.tag = NACL_SRPC_ARG_TYPE_CHAR_ARRAY;
49 2 : out_carray.u.count = NACL_SRPC_MAX_SERVICE_DISCOVERY_CHARS;
50 : /*
51 : * Add one guaranteed NUL byte to make sure the string will be NUL-terminated.
52 : */
53 2 : out_carray.arrays.carr = calloc(NACL_SRPC_MAX_SERVICE_DISCOVERY_CHARS + 1, 1);
54 2 : if (NULL == out_carray.arrays.carr) {
55 : NaClSrpcLog(NACL_SRPC_LOG_ERROR,
56 : "BuildClientService(channel=%p):"
57 : " service discovery malloc failed\n",
58 0 : (void*) channel);
59 0 : goto cleanup;
60 : }
61 : /* Set up the basic service descriptor to make the service discovery call. */
62 2 : tmp_service = (NaClSrpcService*) malloc(sizeof(*tmp_service));
63 2 : if (NULL == tmp_service) {
64 : NaClSrpcLog(NACL_SRPC_LOG_ERROR,
65 : "BuildClientService(channel=%p):"
66 : " temporary service malloc failed\n",
67 0 : (void*) channel);
68 0 : goto cleanup;
69 : }
70 2 : if (!NaClSrpcServiceHandlerCtor(tmp_service, basic_services)) {
71 : NaClSrpcLog(NACL_SRPC_LOG_ERROR,
72 : "BuildClientService(channel=%p):"
73 : " NaClSrpcServiceHandlerCtor failed\n",
74 0 : (void*) channel);
75 0 : free(tmp_service);
76 0 : tmp_service = NULL;
77 0 : goto cleanup;
78 : }
79 : /* Temporarily assign channel->client to allow Invoke. */
80 2 : channel->client = tmp_service;
81 : /* Invoke service discovery, getting description string */
82 2 : service_discovery_result = NaClSrpcInvokeV(channel, 0, ins, outs);
83 : /* Disconnect the temporary service. */
84 2 : channel->client = NULL;
85 2 : if (NACL_SRPC_RESULT_OK != service_discovery_result) {
86 : NaClSrpcLog(NACL_SRPC_LOG_ERROR,
87 : "BuildClientService(channel=%p):"
88 : " service discovery invoke failed\n",
89 0 : (void*) channel);
90 0 : goto cleanup;
91 : }
92 : /* Allocate the real service. */
93 2 : service = (NaClSrpcService*) malloc(sizeof(*service));
94 2 : if (NULL == service) {
95 : NaClSrpcLog(NACL_SRPC_LOG_ERROR,
96 : "BuildClientService(channel=%p):"
97 : " service discovery malloc failed\n",
98 0 : (void*) channel);
99 0 : goto cleanup;
100 : }
101 : /* Build the real service from the resulting string. */
102 2 : if (!NaClSrpcServiceStringCtor(service, out_carray.arrays.carr)) {
103 : NaClSrpcLog(NACL_SRPC_LOG_ERROR,
104 : "BuildClientService(channel=%p):"
105 : " NaClSrpcServiceStringCtor failed\n",
106 0 : (void*) channel);
107 0 : goto cleanup;
108 : }
109 : /* Caller takes ownership of service. */
110 2 : returned_service = service;
111 2 : service = NULL;
112 : cleanup:
113 2 : free(service);
114 2 : NaClSrpcServiceDtor(tmp_service);
115 2 : free(tmp_service);
116 2 : free(out_carray.arrays.carr);
117 2 : return returned_service;
118 2 : }
119 :
120 : /*
121 : * The constructors and destructor.
122 : * Clients and Servers are both NaClSrpcChannels, but they are constructed
123 : * by different methods reflecting how they get their table of rpc methods.
124 : */
125 :
126 2 : void NaClSrpcChannelInitialize(NaClSrpcChannel* channel) {
127 2 : channel->message_channel = NULL;
128 2 : channel->server = NULL;
129 2 : channel->client = NULL;
130 2 : channel->server_instance_data = NULL;
131 2 : }
132 :
133 : static int NaClSrpcChannelCtorHelper(NaClSrpcChannel* channel,
134 2 : NaClSrpcImcDescType handle) {
135 : NaClSrpcLog(1,
136 : "NaClSrpcChannelCtorHelper(channel=%p, handle=%p)\n",
137 : (void*) channel,
138 2 : (void*) handle);
139 : /* Initialize the channel to allow errors to be handled. */
140 2 : NaClSrpcChannelInitialize(channel);
141 : /* Create the message fragmentation layer. */
142 2 : channel->message_channel = NaClSrpcMessageChannelNew(handle);
143 2 : if (NULL == channel->message_channel) {
144 : NaClSrpcLog(NACL_SRPC_LOG_ERROR,
145 : "NaClSrpcChannelCtorHelper(channel=%p):"
146 : " NaClSrpcMessageChannelNew failed\n",
147 0 : (void*) channel);
148 0 : return 0;
149 : }
150 2 : return 1;
151 2 : }
152 :
153 2 : static void NaClSrpcChannelDtorHelper(NaClSrpcChannel* channel) {
154 2 : NaClSrpcLog(1, "NaClSrpcChannelDtorHelper(channel=%p)\n", (void*) channel);
155 2 : channel->server_instance_data = NULL;
156 2 : NaClSrpcMessageChannelDelete(channel->message_channel);
157 2 : channel->message_channel = NULL;
158 2 : }
159 :
160 2 : int NaClSrpcClientCtor(NaClSrpcChannel* channel, NaClSrpcImcDescType handle) {
161 2 : int return_value = 0;
162 2 : NaClSrpcService* client_service = NULL;
163 : NaClSrpcLog(1,
164 : "NaClSrpcClientCtor(channel=%p, handle=%p)\n",
165 : (void*) channel,
166 2 : (void*) handle);
167 2 : if (!NaClSrpcChannelCtorHelper(channel, handle)) {
168 0 : goto cleanup;
169 : }
170 : /* Do service discovery to speed method invocation. */
171 2 : client_service = BuildClientService(channel);
172 2 : if (NULL == client_service) {
173 : NaClSrpcLog(NACL_SRPC_LOG_ERROR,
174 : "NaClSrpcClientCtor(channel=%p):"
175 : " BuildClientService failed\n",
176 0 : (void*) channel);
177 0 : NaClSrpcChannelDtorHelper(channel);
178 0 : goto cleanup;
179 : }
180 : /* Channel takes ownership of client_service. */
181 2 : channel->client = client_service;
182 2 : client_service = NULL;
183 2 : return_value = 1;
184 : cleanup:
185 2 : NaClSrpcServiceDtor(client_service);
186 2 : return return_value;
187 2 : }
188 :
189 : int NaClSrpcServerCtor(NaClSrpcChannel* channel,
190 : NaClSrpcImcDescType handle,
191 : NaClSrpcService* service,
192 2 : void* server_instance_data) {
193 2 : int return_value = 0;
194 : NaClSrpcLog(1,
195 : "NaClSrpcServerCtor(channel=%p, handle=%p,"
196 : " service=%p, server_instance_data=%p)\n",
197 : (void*) channel,
198 : (void*) handle,
199 : (void*) service,
200 2 : (void*) server_instance_data);
201 2 : if (!NaClSrpcChannelCtorHelper(channel, handle)) {
202 0 : goto cleanup;
203 : }
204 : /* Channel takes ownership of service. */
205 2 : channel->server = service;
206 : /* Channel does not take ownership of server_instance_data. */
207 2 : channel->server_instance_data = server_instance_data;
208 2 : return_value = 1;
209 : cleanup:
210 2 : return return_value;
211 2 : }
212 :
213 2 : void NaClSrpcDtor(NaClSrpcChannel* channel) {
214 : NaClSrpcLog(1,
215 : "NaClSrpcDtor(channel=%p)\n",
216 2 : (void*) channel);
217 2 : if (NULL == channel) {
218 0 : return;
219 : }
220 2 : channel->server_instance_data = NULL;
221 2 : NaClSrpcServiceDtor(channel->client);
222 2 : free(channel->client);
223 2 : channel->client = NULL;
224 2 : NaClSrpcServiceDtor(channel->server);
225 2 : free(channel->server);
226 2 : channel->server = NULL;
227 : /* Do the common part destruction. */
228 2 : NaClSrpcChannelDtorHelper(channel);
229 2 : }
230 :
231 2 : void NaClSrpcArgCtor(NaClSrpcArg* arg) {
232 2 : memset(arg, 0, sizeof *arg);
233 2 : }
|