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 : #include "native_client/src/trusted/simple_service/nacl_simple_rservice.h"
8 :
9 : #include "native_client/src/include/nacl_compiler_annotations.h"
10 : #include "native_client/src/shared/platform/nacl_log.h"
11 : #include "native_client/src/shared/platform/nacl_threads.h"
12 : #include "native_client/src/shared/srpc/nacl_srpc.h"
13 :
14 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
15 : #include "native_client/src/trusted/desc/nacl_desc_conn_cap.h"
16 : #include "native_client/src/trusted/desc/nrd_xfer.h"
17 :
18 : #include "native_client/src/trusted/nacl_base/nacl_refcount.h"
19 :
20 : #include "native_client/src/trusted/service_runtime/nacl_config.h"
21 : /* NACL_KERN_STACK_SIZE */
22 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
23 :
24 : int NaClSimpleRevClientCtor(
25 3 : struct NaClSimpleRevClient *self,
26 3 : void (*callback)(
27 : void *state,
28 : struct NaClThreadInterface *tif,
29 : struct NaClDesc *conn),
30 3 : void *state,
31 3 : NaClThreadIfFactoryFunction thread_factory_fn,
32 3 : void *thread_factory_data) {
33 3 : NaClLog(4,
34 : "NaClSimpleRevClientCtor: this 0x%"NACL_PRIxPTR"\n",
35 : (uintptr_t) self);
36 3 : if (!NaClRefCountCtor(&self->base)) {
37 0 : NaClLog(4, "NaClSimpleRevClientCtor: NaClRefCountCtor failed\n");
38 0 : goto done;
39 : }
40 3 : if (0 != NaClCommonDescMakeBoundSock(self->bound_and_cap)) {
41 0 : goto bound_failed;
42 : }
43 :
44 3 : self->acceptor = (struct NaClThreadInterface *) NULL;
45 3 : self->client_callback = callback;
46 3 : self->state = state;
47 3 : self->thread_factory_fn = thread_factory_fn;
48 3 : self->thread_factory_data = thread_factory_data;
49 3 : NaClLog(4,
50 : ("NaClSimpleRevClientCtor: callback 0x%"NACL_PRIxPTR
51 : ", state 0x%"NACL_PRIxPTR"\n"),
52 : (uintptr_t) callback,
53 : (uintptr_t) state);
54 3 : NACL_VTBL(NaClRefCount, self) =
55 : (struct NaClRefCountVtbl *) &kNaClSimpleRevClientVtbl;
56 3 : return 1;
57 :
58 : bound_failed:
59 0 : (*NACL_VTBL(NaClRefCount, self)->Dtor)(&self->base);
60 : done:
61 0 : return 0;
62 3 : }
63 :
64 0 : static void NaClSimpleRevClientDtor(struct NaClRefCount *vself) {
65 0 : struct NaClSimpleRevClient *self =
66 : (struct NaClSimpleRevClient *) vself;
67 :
68 0 : NaClDescUnref(self->bound_and_cap[0]);
69 0 : NaClDescUnref(self->bound_and_cap[1]);
70 :
71 0 : NACL_VTBL(NaClRefCount, self) = &kNaClRefCountVtbl;
72 0 : (*NACL_VTBL(NaClRefCount, self)->Dtor)(&self->base);
73 0 : }
74 :
75 : struct NaClSimpleRevClientVtbl const kNaClSimpleRevClientVtbl = {
76 : {
77 : NaClSimpleRevClientDtor,
78 : },
79 : };
80 :
81 3 : static void *RevRpcHandlerBase(struct NaClThreadInterface *tif) {
82 3 : struct NaClSimpleRevClient *self =
83 : (struct NaClSimpleRevClient *) tif->thread_data;
84 :
85 3 : int status;
86 3 : struct NaClDesc *conn;
87 :
88 3 : NaClLog(4, "Entered RevRpcHandlerBase\n");
89 3 : while (0 == (status =
90 4 : (*NACL_VTBL(NaClDesc, self->bound_and_cap[0])->AcceptConn)(
91 : self->bound_and_cap[0], &conn))) {
92 4 : NaClLog(4,
93 : ("RevRpcHandlerBase: Accept returned success,"
94 : " invoking callback"
95 : " 0x%"NACL_PRIxPTR"(0x%"NACL_PRIxPTR",0x%"NACL_PRIxPTR")\n"),
96 : (uintptr_t) self->client_callback,
97 : (uintptr_t) self->state,
98 : (uintptr_t) conn);
99 : /*
100 : * The callback should not block; if needed, it should spawn
101 : * another thread. The callback takes ownership of |conn| -- it
102 : * may Unref |conn| prior to returning or the ownership of |conn|
103 : * may be passed to another thread (e.g., newly spawned, or waking
104 : * up and giving |conn| to the thread that made the connection
105 : * request in the first place).
106 : */
107 4 : (*self->client_callback)(self->state, tif, conn);
108 4 : NaClLog(4,
109 : "RevRpcHandlerBase: callback finished.\n");
110 4 : }
111 0 : NaClLog(LOG_INFO,
112 : ("NaClSimpleRevClient::RevRpcHandlerBase:"
113 : " AcceptConn failed, status %d\n"),
114 : status);
115 : /*
116 : * The unref of self may Dtor the currently running thread. This is
117 : * okay, since this only removes the ability to use the thread
118 : * handle (in Windows) but does not otherwise affect the thread. We
119 : * don't log afterwards, just in case the logging code (is later
120 : * modified to) use thread info.
121 : */
122 0 : NaClRefCountUnref((struct NaClRefCount *) self);
123 0 : return (void *) NULL;
124 : }
125 :
126 3 : int NaClSimpleRevClientStartServiceThread(struct NaClSimpleRevClient *self) {
127 3 : NaClLog(4, "Entered NaClSimpleRevClientStartServiceThread\n");
128 3 : if (NULL != self->acceptor) {
129 0 : NaClLog(LOG_FATAL,
130 : "NaClSimpleRevClientStartServiceThread: dup - already started\n");
131 0 : }
132 6 : if (!NaClThreadInterfaceConstructAndStartThread(
133 : self->thread_factory_fn,
134 : self->thread_factory_data,
135 : RevRpcHandlerBase,
136 3 : NaClRefCountRef((struct NaClRefCount *) self),
137 : NACL_KERN_STACK_SIZE,
138 : &self->acceptor)) {
139 0 : NaClLog(4, "NaClSimpleRevClientStartServiceThread: no thread\n");
140 0 : NaClRefCountUnref((struct NaClRefCount *) self);
141 0 : return 0;
142 : }
143 3 : return 1;
144 3 : }
145 :
146 : int NaClSimpleRevServiceCtor(
147 5 : struct NaClSimpleRevService *self,
148 5 : struct NaClDesc *conn_cap,
149 5 : struct NaClSrpcHandlerDesc const *handlers,
150 5 : NaClThreadIfFactoryFunction thread_factory_fn,
151 5 : void *thread_factory_data) {
152 5 : NaClLog(4,
153 : "NaClSimpleRevServiceCtor: this 0x%"NACL_PRIxPTR"\n",
154 : (uintptr_t) self);
155 5 : if (!NaClRefCountCtor(&self->base)) {
156 0 : NaClLog(4, "NaClSimpleRevServiceCtor: NaClRefCountCtor failed\n");
157 0 : return 0;
158 : }
159 5 : self->conn_cap = conn_cap; /* take ownership, if ctor succeeds */
160 5 : self->handlers = handlers;
161 : /* caller ensures lifetime of handlers is at least that of self */
162 5 : self->thread_factory_fn = thread_factory_fn;
163 5 : self->thread_factory_data = thread_factory_data;
164 :
165 5 : NACL_VTBL(NaClRefCount, self) =
166 : (struct NaClRefCountVtbl *) &kNaClSimpleRevServiceVtbl;
167 :
168 5 : NaClLog(4, "Leaving NaClSimpleRevServiceCtor\n");
169 5 : return 1;
170 5 : }
171 :
172 5 : void NaClSimpleRevServiceDtor(struct NaClRefCount *vself) {
173 5 : struct NaClSimpleRevService *self =
174 : (struct NaClSimpleRevService *) vself;
175 :
176 5 : NaClDescUnref(self->conn_cap);
177 5 : self->conn_cap = NULL;
178 5 : self->handlers = NULL;
179 :
180 5 : NACL_VTBL(NaClRefCount, self) = &kNaClRefCountVtbl;
181 5 : (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
182 5 : }
183 :
184 8 : static void *ConnRpcBase(struct NaClThreadInterface *tif) {
185 8 : struct NaClSimpleRevConnection *rev_conn =
186 : (struct NaClSimpleRevConnection *) tif->thread_data;
187 :
188 8 : NaClLog(4, "Entered ConnRpcBase, invoking RpcHandler vfn\n");
189 8 : (*NACL_VTBL(NaClSimpleRevService, rev_conn->service)->RpcHandler)(
190 : rev_conn->service, rev_conn);
191 8 : NaClLog(4, "Leaving ConnRpcBase\n");
192 8 : NaClRefCountUnref((struct NaClRefCount *) rev_conn);
193 8 : return (void *) NULL;
194 : }
195 :
196 : int NaClSimpleRevServiceConnectAndSpawnHandlerCb(
197 8 : struct NaClSimpleRevService *self,
198 8 : void (*exit_cb)(void *instance_data,
199 : int server_loop_ret),
200 8 : void *instance_data) {
201 8 : int status;
202 8 : struct NaClDesc *conn = NULL;
203 8 : struct NaClSimpleRevConnection *rev_conn;
204 :
205 8 : NaClLog(4, "Entered NaClSimpleRevServiceConnectAndSpawnHandler\n");
206 : if (0 != (status =
207 8 : (*NACL_VTBL(NaClDesc, self->conn_cap)->ConnectAddr)(
208 : self->conn_cap, &conn))) {
209 : /* failed */
210 0 : NaClLog(3, "NaClSimpleRevServiceConnectAndSpawnHandler: connect failed\n");
211 0 : return status;
212 : }
213 : if (0 != (status =
214 8 : (*NACL_VTBL(NaClSimpleRevService, self)->RevConnectionFactory)(
215 : self, conn, exit_cb, instance_data, &rev_conn))) {
216 0 : NaClDescUnref(conn);
217 0 : NaClLog(3,
218 : ("NaClSimpleRevServiceConnectAndSpawnHandler: factory failed,"
219 : " error %d\n"),
220 : status);
221 0 : return status;
222 : }
223 8 : conn = NULL; /* rev_conn owns the ref in conn now */
224 : /*
225 : * Spawn thread to use the NaClSimpleRevConnection.
226 : */
227 : /* rev_conn not visible to other threads, ownership passed to thread */
228 8 : if (!NaClThreadInterfaceConstructAndStartThread(
229 : self->thread_factory_fn,
230 : self->thread_factory_data,
231 : ConnRpcBase,
232 : (void *) rev_conn,
233 : NACL_KERN_STACK_SIZE,
234 : &rev_conn->thread)) {
235 : /*
236 : * no thread, clean up
237 : */
238 0 : NaClLog(3, "NaClSimpleRevServiceConnectAndSpawnHandler: no thread\n");
239 0 : NaClRefCountUnref((struct NaClRefCount *) rev_conn);
240 0 : return -NACL_ABI_EAGAIN;
241 : }
242 : /* thread owns rev_conn */
243 8 : NaClLog(4, "Leaving NaClSimpleRevServiceConnectAndSpawnHandler\n");
244 8 : return 0;
245 8 : }
246 :
247 : int NaClSimpleRevServiceConnectAndSpawnHandler(
248 0 : struct NaClSimpleRevService *self,
249 0 : void *instance_data) {
250 0 : return NaClSimpleRevServiceConnectAndSpawnHandlerCb(
251 : self, NULL, instance_data);
252 : }
253 :
254 : int NaClSimpleRevServiceConnectionFactory(
255 8 : struct NaClSimpleRevService *self,
256 8 : struct NaClDesc *conn,
257 8 : void (*exit_cb)(void *instance_data,
258 : int server_loop_ret),
259 8 : void *instance_data,
260 8 : struct NaClSimpleRevConnection **out) {
261 8 : struct NaClSimpleRevConnection *rconn;
262 :
263 8 : rconn = (struct NaClSimpleRevConnection *) malloc(sizeof *rconn);
264 8 : if (NULL == rconn) {
265 0 : NaClLog(4, "NaClSimpleRevServiceConnectionFactory:"
266 : " no memory\n");
267 0 : return -NACL_ABI_EAGAIN;
268 : }
269 : /*
270 : * In the common/degenerate case, factory instance_data becomes
271 : * connection instance data.
272 : */
273 8 : if (!NaClSimpleRevConnectionCtor(rconn, self, conn,
274 : exit_cb, instance_data)) {
275 0 : NaClLog(4, "NaClSimpleRevServiceConnectionFactory:"
276 : " NaClSimpleRevConnectionCtor failed\n");
277 0 : free(rconn);
278 0 : return -NACL_ABI_EINVAL;
279 : }
280 :
281 8 : *out = rconn;
282 8 : return 0;
283 8 : }
284 :
285 : void NaClSimpleRevServiceRpcHandler(
286 8 : struct NaClSimpleRevService *self,
287 8 : struct NaClSimpleRevConnection *conn) {
288 8 : int retval;
289 :
290 8 : NaClLog(4, "Entered NaClSimpleRevServiceRpcHandler: ServerLoop!\n");
291 8 : retval = NaClSrpcServerLoop(conn->connected_socket,
292 : self->handlers,
293 : conn->instance_data);
294 8 : NaClLog(4,
295 : "NaClSimpleRevServiceRpcHandler: NaClSrpcServerLoop returned %d\n",
296 : retval);
297 8 : if (NULL != conn->exit_cb) {
298 5 : (*conn->exit_cb)(conn->instance_data, retval);
299 5 : }
300 8 : NaClLog(4, "Leaving NaClSimpleRevServiceRpcHandler\n");
301 8 : }
302 :
303 : struct NaClSimpleRevServiceVtbl const kNaClSimpleRevServiceVtbl = {
304 : {
305 : NaClSimpleRevServiceDtor,
306 : },
307 : NaClSimpleRevServiceConnectAndSpawnHandler,
308 : NaClSimpleRevServiceConnectAndSpawnHandlerCb,
309 : NaClSimpleRevServiceConnectionFactory,
310 : NaClSimpleRevServiceRpcHandler,
311 : };
312 :
313 : int NaClSimpleRevConnectionCtor(
314 8 : struct NaClSimpleRevConnection *self,
315 8 : struct NaClSimpleRevService *service,
316 8 : struct NaClDesc *conn,
317 8 : void (*exit_cb)(void *instance_data,
318 : int server_loop_ret),
319 8 : void *instance_data) {
320 8 : NaClLog(4,
321 : "NaClSimpleRevConnectionCtor: this 0x%"NACL_PRIxPTR"\n",
322 : (uintptr_t) self);
323 8 : if (!NaClRefCountCtor(&self->base)) {
324 0 : return 0;
325 : }
326 :
327 8 : NaClRefCountRef((struct NaClRefCount *) service);
328 8 : self->service = service;
329 8 : self->connected_socket = conn;
330 8 : self->exit_cb = exit_cb;
331 8 : self->instance_data = instance_data;
332 :
333 8 : NACL_VTBL(NaClRefCount, self) =
334 : (struct NaClRefCountVtbl *) &kNaClSimpleRevConnectionVtbl;
335 8 : return 1;
336 8 : }
337 :
338 8 : void NaClSimpleRevConnectionDtor(struct NaClRefCount *vself) {
339 8 : struct NaClSimpleRevConnection *self =
340 : (struct NaClSimpleRevConnection *) vself;
341 :
342 8 : NaClRefCountUnref((struct NaClRefCount *) self->service);
343 8 : NaClRefCountUnref((struct NaClRefCount *) self->connected_socket);
344 :
345 8 : NACL_VTBL(NaClRefCount, self) = &kNaClRefCountVtbl;
346 8 : (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
347 8 : }
348 :
349 : struct NaClRefCountVtbl kNaClSimpleRevConnectionVtbl = {
350 : NaClSimpleRevConnectionDtor,
351 : };
|