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.
7 #include "native_client/src/trusted/simple_service/nacl_simple_rservice.h"
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"
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"
18 #include "native_client/src/trusted/nacl_base/nacl_refcount.h"
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"
24 int NaClSimpleRevClientCtor(
25 struct NaClSimpleRevClient *self,
28 struct NaClThreadInterface *tif,
29 struct NaClDesc *conn),
31 NaClThreadIfFactoryFunction thread_factory_fn,
32 void *thread_factory_data) {
34 "NaClSimpleRevClientCtor: this 0x%"NACL_PRIxPTR"\n",
36 if (!NaClRefCountCtor(&self->base)) {
37 NaClLog(4, "NaClSimpleRevClientCtor: NaClRefCountCtor failed\n");
40 if (0 != NaClCommonDescMakeBoundSock(self->bound_and_cap)) {
44 self->acceptor = (struct NaClThreadInterface *) NULL;
45 self->client_callback = callback;
47 self->thread_factory_fn = thread_factory_fn;
48 self->thread_factory_data = thread_factory_data;
50 ("NaClSimpleRevClientCtor: callback 0x%"NACL_PRIxPTR
51 ", state 0x%"NACL_PRIxPTR"\n"),
54 NACL_VTBL(NaClRefCount, self) =
55 (struct NaClRefCountVtbl *) &kNaClSimpleRevClientVtbl;
59 (*NACL_VTBL(NaClRefCount, self)->Dtor)(&self->base);
64 static void NaClSimpleRevClientDtor(struct NaClRefCount *vself) {
65 struct NaClSimpleRevClient *self =
66 (struct NaClSimpleRevClient *) vself;
68 NaClDescUnref(self->bound_and_cap[0]);
69 NaClDescUnref(self->bound_and_cap[1]);
71 NACL_VTBL(NaClRefCount, self) = &kNaClRefCountVtbl;
72 (*NACL_VTBL(NaClRefCount, self)->Dtor)(&self->base);
75 struct NaClSimpleRevClientVtbl const kNaClSimpleRevClientVtbl = {
77 NaClSimpleRevClientDtor,
81 static void *RevRpcHandlerBase(struct NaClThreadInterface *tif) {
82 struct NaClSimpleRevClient *self =
83 (struct NaClSimpleRevClient *) tif->thread_data;
86 struct NaClDesc *conn;
88 NaClLog(4, "Entered RevRpcHandlerBase\n");
90 (*NACL_VTBL(NaClDesc, self->bound_and_cap[0])->AcceptConn)(
91 self->bound_and_cap[0], &conn))) {
93 ("RevRpcHandlerBase: Accept returned success,"
95 " 0x%"NACL_PRIxPTR"(0x%"NACL_PRIxPTR",0x%"NACL_PRIxPTR")\n"),
96 (uintptr_t) self->client_callback,
97 (uintptr_t) self->state,
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).
107 (*self->client_callback)(self->state, tif, conn);
109 "RevRpcHandlerBase: callback finished.\n");
112 ("NaClSimpleRevClient::RevRpcHandlerBase:"
113 " AcceptConn failed, status %d\n"),
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.
122 NaClRefCountUnref((struct NaClRefCount *) self);
123 return (void *) NULL;
126 int NaClSimpleRevClientStartServiceThread(struct NaClSimpleRevClient *self) {
127 NaClLog(4, "Entered NaClSimpleRevClientStartServiceThread\n");
128 if (NULL != self->acceptor) {
130 "NaClSimpleRevClientStartServiceThread: dup - already started\n");
132 if (!NaClThreadInterfaceConstructAndStartThread(
133 self->thread_factory_fn,
134 self->thread_factory_data,
136 NaClRefCountRef((struct NaClRefCount *) self),
137 NACL_KERN_STACK_SIZE,
139 NaClLog(4, "NaClSimpleRevClientStartServiceThread: no thread\n");
140 NaClRefCountUnref((struct NaClRefCount *) self);
146 int NaClSimpleRevServiceCtor(
147 struct NaClSimpleRevService *self,
148 struct NaClDesc *conn_cap,
149 struct NaClSrpcHandlerDesc const *handlers,
150 NaClThreadIfFactoryFunction thread_factory_fn,
151 void *thread_factory_data) {
153 "NaClSimpleRevServiceCtor: this 0x%"NACL_PRIxPTR"\n",
155 if (!NaClRefCountCtor(&self->base)) {
156 NaClLog(4, "NaClSimpleRevServiceCtor: NaClRefCountCtor failed\n");
159 self->conn_cap = conn_cap; /* take ownership, if ctor succeeds */
160 self->handlers = handlers;
161 /* caller ensures lifetime of handlers is at least that of self */
162 self->thread_factory_fn = thread_factory_fn;
163 self->thread_factory_data = thread_factory_data;
165 NACL_VTBL(NaClRefCount, self) =
166 (struct NaClRefCountVtbl *) &kNaClSimpleRevServiceVtbl;
168 NaClLog(4, "Leaving NaClSimpleRevServiceCtor\n");
172 void NaClSimpleRevServiceDtor(struct NaClRefCount *vself) {
173 struct NaClSimpleRevService *self =
174 (struct NaClSimpleRevService *) vself;
176 NaClDescUnref(self->conn_cap);
177 self->conn_cap = NULL;
178 self->handlers = NULL;
180 NACL_VTBL(NaClRefCount, self) = &kNaClRefCountVtbl;
181 (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
184 static void *ConnRpcBase(struct NaClThreadInterface *tif) {
185 struct NaClSimpleRevConnection *rev_conn =
186 (struct NaClSimpleRevConnection *) tif->thread_data;
188 NaClLog(4, "Entered ConnRpcBase, invoking RpcHandler vfn\n");
189 (*NACL_VTBL(NaClSimpleRevService, rev_conn->service)->RpcHandler)(
190 rev_conn->service, rev_conn);
191 NaClLog(4, "Leaving ConnRpcBase\n");
192 NaClRefCountUnref((struct NaClRefCount *) rev_conn);
193 return (void *) NULL;
196 int NaClSimpleRevServiceConnectAndSpawnHandlerCb(
197 struct NaClSimpleRevService *self,
198 void (*exit_cb)(void *instance_data,
199 int server_loop_ret),
200 void *instance_data) {
202 struct NaClDesc *conn = NULL;
203 struct NaClSimpleRevConnection *rev_conn;
205 NaClLog(4, "Entered NaClSimpleRevServiceConnectAndSpawnHandler\n");
207 (*NACL_VTBL(NaClDesc, self->conn_cap)->ConnectAddr)(
208 self->conn_cap, &conn))) {
210 NaClLog(3, "NaClSimpleRevServiceConnectAndSpawnHandler: connect failed\n");
214 (*NACL_VTBL(NaClSimpleRevService, self)->RevConnectionFactory)(
215 self, conn, exit_cb, instance_data, &rev_conn))) {
218 ("NaClSimpleRevServiceConnectAndSpawnHandler: factory failed,"
223 conn = NULL; /* rev_conn owns the ref in conn now */
225 * Spawn thread to use the NaClSimpleRevConnection.
227 /* rev_conn not visible to other threads, ownership passed to thread */
228 if (!NaClThreadInterfaceConstructAndStartThread(
229 self->thread_factory_fn,
230 self->thread_factory_data,
233 NACL_KERN_STACK_SIZE,
234 &rev_conn->thread)) {
236 * no thread, clean up
238 NaClLog(3, "NaClSimpleRevServiceConnectAndSpawnHandler: no thread\n");
239 NaClRefCountUnref((struct NaClRefCount *) rev_conn);
240 return -NACL_ABI_EAGAIN;
242 /* thread owns rev_conn */
243 NaClLog(4, "Leaving NaClSimpleRevServiceConnectAndSpawnHandler\n");
247 int NaClSimpleRevServiceConnectAndSpawnHandler(
248 struct NaClSimpleRevService *self,
249 void *instance_data) {
250 return NaClSimpleRevServiceConnectAndSpawnHandlerCb(
251 self, NULL, instance_data);
254 int NaClSimpleRevServiceConnectionFactory(
255 struct NaClSimpleRevService *self,
256 struct NaClDesc *conn,
257 void (*exit_cb)(void *instance_data,
258 int server_loop_ret),
260 struct NaClSimpleRevConnection **out) {
261 struct NaClSimpleRevConnection *rconn;
263 rconn = (struct NaClSimpleRevConnection *) malloc(sizeof *rconn);
265 NaClLog(4, "NaClSimpleRevServiceConnectionFactory:"
267 return -NACL_ABI_EAGAIN;
270 * In the common/degenerate case, factory instance_data becomes
271 * connection instance data.
273 if (!NaClSimpleRevConnectionCtor(rconn, self, conn,
274 exit_cb, instance_data)) {
275 NaClLog(4, "NaClSimpleRevServiceConnectionFactory:"
276 " NaClSimpleRevConnectionCtor failed\n");
278 return -NACL_ABI_EINVAL;
285 void NaClSimpleRevServiceRpcHandler(
286 struct NaClSimpleRevService *self,
287 struct NaClSimpleRevConnection *conn) {
290 NaClLog(4, "Entered NaClSimpleRevServiceRpcHandler: ServerLoop!\n");
291 retval = NaClSrpcServerLoop(conn->connected_socket,
293 conn->instance_data);
295 "NaClSimpleRevServiceRpcHandler: NaClSrpcServerLoop returned %d\n",
297 if (NULL != conn->exit_cb) {
298 (*conn->exit_cb)(conn->instance_data, retval);
300 NaClLog(4, "Leaving NaClSimpleRevServiceRpcHandler\n");
303 struct NaClSimpleRevServiceVtbl const kNaClSimpleRevServiceVtbl = {
305 NaClSimpleRevServiceDtor,
307 NaClSimpleRevServiceConnectAndSpawnHandler,
308 NaClSimpleRevServiceConnectAndSpawnHandlerCb,
309 NaClSimpleRevServiceConnectionFactory,
310 NaClSimpleRevServiceRpcHandler,
313 int NaClSimpleRevConnectionCtor(
314 struct NaClSimpleRevConnection *self,
315 struct NaClSimpleRevService *service,
316 struct NaClDesc *conn,
317 void (*exit_cb)(void *instance_data,
318 int server_loop_ret),
319 void *instance_data) {
321 "NaClSimpleRevConnectionCtor: this 0x%"NACL_PRIxPTR"\n",
323 if (!NaClRefCountCtor(&self->base)) {
327 NaClRefCountRef((struct NaClRefCount *) service);
328 self->service = service;
329 self->connected_socket = conn;
330 self->exit_cb = exit_cb;
331 self->instance_data = instance_data;
333 NACL_VTBL(NaClRefCount, self) =
334 (struct NaClRefCountVtbl *) &kNaClSimpleRevConnectionVtbl;
338 void NaClSimpleRevConnectionDtor(struct NaClRefCount *vself) {
339 struct NaClSimpleRevConnection *self =
340 (struct NaClSimpleRevConnection *) vself;
342 NaClRefCountUnref((struct NaClRefCount *) self->service);
343 NaClRefCountUnref((struct NaClRefCount *) self->connected_socket);
345 NACL_VTBL(NaClRefCount, self) = &kNaClRefCountVtbl;
346 (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
349 struct NaClRefCountVtbl kNaClSimpleRevConnectionVtbl = {
350 NaClSimpleRevConnectionDtor,