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 : struct NaClSimpleRevClient *self,
26 : void (*callback)(
27 : void *state,
28 : struct NaClThreadInterface *tif,
29 : struct NaClDesc *conn),
30 : void *state,
31 : NaClThreadIfFactoryFunction thread_factory_fn,
32 0 : void *thread_factory_data) {
33 0 : NaClLog(4,
34 : "NaClSimpleRevClientCtor: this 0x%"NACL_PRIxPTR"\n",
35 : (uintptr_t) self);
36 0 : if (!NaClRefCountCtor(&self->base)) {
37 0 : NaClLog(4, "NaClSimpleRevClientCtor: NaClRefCountCtor failed\n");
38 0 : goto done;
39 : }
40 0 : if (0 != NaClCommonDescMakeBoundSock(self->bound_and_cap)) {
41 0 : goto bound_failed;
42 : }
43 :
44 0 : self->acceptor = (struct NaClThreadInterface *) NULL;
45 0 : self->client_callback = callback;
46 0 : self->state = state;
47 0 : self->thread_factory_fn = thread_factory_fn;
48 0 : self->thread_factory_data = thread_factory_data;
49 0 : NaClLog(4,
50 : ("NaClSimpleRevClientCtor: callback 0x%"NACL_PRIxPTR
51 : ", state 0x%"NACL_PRIxPTR"\n"),
52 : (uintptr_t) callback,
53 : (uintptr_t) state);
54 0 : NACL_VTBL(NaClRefCount, self) =
55 : (struct NaClRefCountVtbl *) &kNaClSimpleRevClientVtbl;
56 0 : return 1;
57 :
58 0 : bound_failed:
59 0 : (*NACL_VTBL(NaClRefCount, self)->Dtor)(&self->base);
60 0 : done:
61 0 : return 0;
62 : }
63 :
64 0 : static void NaClSimpleRevClientDtor(struct NaClRefCount *vself) {
65 : struct NaClSimpleRevClient *self =
66 0 : (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 0 : static void *RevRpcHandlerBase(struct NaClThreadInterface *tif) {
82 : struct NaClSimpleRevClient *self =
83 0 : (struct NaClSimpleRevClient *) tif->thread_data;
84 :
85 : int status;
86 : struct NaClDesc *conn;
87 :
88 0 : NaClLog(4, "Entered RevRpcHandlerBase\n");
89 0 : while (0 == (status =
90 : (*NACL_VTBL(NaClDesc, self->bound_and_cap[0])->AcceptConn)(
91 : self->bound_and_cap[0], &conn))) {
92 0 : 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 0 : (*self->client_callback)(self->state, tif, conn);
108 0 : NaClLog(4,
109 : "RevRpcHandlerBase: callback finished.\n");
110 : }
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 0 : int NaClSimpleRevClientStartServiceThread(struct NaClSimpleRevClient *self) {
127 0 : NaClLog(4, "Entered NaClSimpleRevClientStartServiceThread\n");
128 0 : if (NULL != self->acceptor) {
129 0 : NaClLog(LOG_FATAL,
130 : "NaClSimpleRevClientStartServiceThread: dup - already started\n");
131 : }
132 0 : if (!NaClThreadInterfaceConstructAndStartThread(
133 : self->thread_factory_fn,
134 : self->thread_factory_data,
135 : RevRpcHandlerBase,
136 : 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 : self->acceptor = NULL;
142 0 : return 0;
143 : }
144 0 : return 1;
145 : }
146 :
147 : int NaClSimpleRevServiceCtor(
148 : struct NaClSimpleRevService *self,
149 : struct NaClDesc *conn_cap,
150 : struct NaClSrpcHandlerDesc const *handlers,
151 : NaClThreadIfFactoryFunction thread_factory_fn,
152 5 : void *thread_factory_data) {
153 5 : NaClLog(4,
154 : "NaClSimpleRevServiceCtor: this 0x%"NACL_PRIxPTR"\n",
155 : (uintptr_t) self);
156 5 : if (!NaClRefCountCtor(&self->base)) {
157 0 : NaClLog(4, "NaClSimpleRevServiceCtor: NaClRefCountCtor failed\n");
158 0 : return 0;
159 : }
160 5 : self->conn_cap = conn_cap; /* take ownership, if ctor succeeds */
161 5 : self->handlers = handlers;
162 : /* caller ensures lifetime of handlers is at least that of self */
163 5 : self->thread_factory_fn = thread_factory_fn;
164 5 : self->thread_factory_data = thread_factory_data;
165 :
166 5 : NACL_VTBL(NaClRefCount, self) =
167 : (struct NaClRefCountVtbl *) &kNaClSimpleRevServiceVtbl;
168 :
169 5 : NaClLog(4, "Leaving NaClSimpleRevServiceCtor\n");
170 5 : return 1;
171 : }
172 :
173 2 : void NaClSimpleRevServiceDtor(struct NaClRefCount *vself) {
174 : struct NaClSimpleRevService *self =
175 2 : (struct NaClSimpleRevService *) vself;
176 :
177 2 : NaClDescUnref(self->conn_cap);
178 2 : self->conn_cap = NULL;
179 2 : self->handlers = NULL;
180 :
181 2 : NACL_VTBL(NaClRefCount, self) = &kNaClRefCountVtbl;
182 2 : (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
183 2 : }
184 :
185 5 : static void *ConnRpcBase(struct NaClThreadInterface *tif) {
186 : struct NaClSimpleRevConnection *rev_conn =
187 5 : (struct NaClSimpleRevConnection *) tif->thread_data;
188 :
189 5 : NaClLog(4, "Entered ConnRpcBase, invoking RpcHandler vfn\n");
190 5 : (*NACL_VTBL(NaClSimpleRevService, rev_conn->service)->RpcHandler)(
191 : rev_conn->service, rev_conn);
192 5 : NaClLog(4, "Leaving ConnRpcBase\n");
193 5 : NaClRefCountUnref((struct NaClRefCount *) rev_conn);
194 5 : return (void *) NULL;
195 : }
196 :
197 : int NaClSimpleRevServiceConnectAndSpawnHandlerCb(
198 : struct NaClSimpleRevService *self,
199 : void (*exit_cb)(void *instance_data,
200 : int server_loop_ret),
201 5 : void *instance_data) {
202 : int status;
203 5 : struct NaClDesc *conn = NULL;
204 : struct NaClSimpleRevConnection *rev_conn;
205 :
206 5 : NaClLog(4, "Entered NaClSimpleRevServiceConnectAndSpawnHandler\n");
207 5 : if (0 != (status =
208 : (*NACL_VTBL(NaClDesc, self->conn_cap)->ConnectAddr)(
209 : self->conn_cap, &conn))) {
210 : /* failed */
211 0 : NaClLog(3, "NaClSimpleRevServiceConnectAndSpawnHandler: connect failed\n");
212 0 : return status;
213 : }
214 5 : if (0 != (status =
215 : (*NACL_VTBL(NaClSimpleRevService, self)->RevConnectionFactory)(
216 : self, conn, exit_cb, instance_data, &rev_conn))) {
217 0 : NaClDescUnref(conn);
218 0 : NaClLog(3,
219 : ("NaClSimpleRevServiceConnectAndSpawnHandler: factory failed,"
220 : " error %d\n"),
221 : status);
222 0 : return status;
223 : }
224 5 : conn = NULL; /* rev_conn owns the ref in conn now */
225 : /*
226 : * Spawn thread to use the NaClSimpleRevConnection.
227 : */
228 : /* rev_conn not visible to other threads, ownership passed to thread */
229 5 : if (!NaClThreadInterfaceConstructAndStartThread(
230 : self->thread_factory_fn,
231 : self->thread_factory_data,
232 : ConnRpcBase,
233 : (void *) rev_conn,
234 : NACL_KERN_STACK_SIZE,
235 : &rev_conn->thread)) {
236 : /*
237 : * no thread, clean up
238 : */
239 0 : NaClLog(3, "NaClSimpleRevServiceConnectAndSpawnHandler: no thread\n");
240 0 : NaClRefCountUnref((struct NaClRefCount *) rev_conn);
241 0 : rev_conn->thread = NULL;
242 0 : return -NACL_ABI_EAGAIN;
243 : }
244 : /* thread owns rev_conn */
245 5 : NaClLog(4, "Leaving NaClSimpleRevServiceConnectAndSpawnHandler\n");
246 5 : return 0;
247 : }
248 :
249 : int NaClSimpleRevServiceConnectAndSpawnHandler(
250 : struct NaClSimpleRevService *self,
251 0 : void *instance_data) {
252 0 : return NaClSimpleRevServiceConnectAndSpawnHandlerCb(
253 : self, NULL, instance_data);
254 : }
255 :
256 : int NaClSimpleRevServiceConnectionFactory(
257 : struct NaClSimpleRevService *self,
258 : struct NaClDesc *conn,
259 : void (*exit_cb)(void *instance_data,
260 : int server_loop_ret),
261 : void *instance_data,
262 5 : struct NaClSimpleRevConnection **out) {
263 : struct NaClSimpleRevConnection *rconn;
264 :
265 5 : rconn = (struct NaClSimpleRevConnection *) malloc(sizeof *rconn);
266 5 : if (NULL == rconn) {
267 0 : NaClLog(4, "NaClSimpleRevServiceConnectionFactory:"
268 : " no memory\n");
269 0 : return -NACL_ABI_EAGAIN;
270 : }
271 : /*
272 : * In the common/degenerate case, factory instance_data becomes
273 : * connection instance data.
274 : */
275 5 : if (!NaClSimpleRevConnectionCtor(rconn, self, conn,
276 : exit_cb, instance_data)) {
277 0 : NaClLog(4, "NaClSimpleRevServiceConnectionFactory:"
278 : " NaClSimpleRevConnectionCtor failed\n");
279 0 : free(rconn);
280 0 : return -NACL_ABI_EINVAL;
281 : }
282 :
283 5 : *out = rconn;
284 5 : return 0;
285 : }
286 :
287 : void NaClSimpleRevServiceRpcHandler(
288 : struct NaClSimpleRevService *self,
289 5 : struct NaClSimpleRevConnection *conn) {
290 : int retval;
291 :
292 5 : NaClLog(4, "Entered NaClSimpleRevServiceRpcHandler: ServerLoop!\n");
293 5 : retval = NaClSrpcServerLoop(conn->connected_socket,
294 : self->handlers,
295 : conn->instance_data);
296 5 : NaClLog(4,
297 : "NaClSimpleRevServiceRpcHandler: NaClSrpcServerLoop returned %d\n",
298 : retval);
299 5 : if (NULL != conn->exit_cb) {
300 2 : (*conn->exit_cb)(conn->instance_data, retval);
301 : }
302 5 : NaClLog(4, "Leaving NaClSimpleRevServiceRpcHandler\n");
303 5 : }
304 :
305 : struct NaClSimpleRevServiceVtbl const kNaClSimpleRevServiceVtbl = {
306 : {
307 : NaClSimpleRevServiceDtor,
308 : },
309 : NaClSimpleRevServiceConnectAndSpawnHandler,
310 : NaClSimpleRevServiceConnectAndSpawnHandlerCb,
311 : NaClSimpleRevServiceConnectionFactory,
312 : NaClSimpleRevServiceRpcHandler,
313 : };
314 :
315 : int NaClSimpleRevConnectionCtor(
316 : struct NaClSimpleRevConnection *self,
317 : struct NaClSimpleRevService *service,
318 : struct NaClDesc *conn,
319 : void (*exit_cb)(void *instance_data,
320 : int server_loop_ret),
321 5 : void *instance_data) {
322 5 : NaClLog(4,
323 : "NaClSimpleRevConnectionCtor: this 0x%"NACL_PRIxPTR"\n",
324 : (uintptr_t) self);
325 5 : if (!NaClRefCountCtor(&self->base)) {
326 0 : return 0;
327 : }
328 :
329 5 : self->service = service;
330 5 : self->connected_socket = conn;
331 5 : self->exit_cb = exit_cb;
332 5 : self->instance_data = instance_data;
333 :
334 5 : return 1;
335 : }
336 :
337 0 : void NaClSimpleRevConnectionDtor(struct NaClRefCount *vself) {
338 : struct NaClSimpleRevConnection *self =
339 0 : (struct NaClSimpleRevConnection *) vself;
340 :
341 0 : NaClRefCountUnref((struct NaClRefCount *) self->service);
342 0 : NaClRefCountUnref((struct NaClRefCount *) self->connected_socket);
343 :
344 0 : NACL_VTBL(NaClRefCount, self) = &kNaClRefCountVtbl;
345 0 : (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
346 0 : }
347 :
348 : struct NaClRefCountVtbl kNaClSimpleRevConnectionVtbl = {
349 : NaClSimpleRevConnectionDtor,
350 : };
|