Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / native_client / src / trusted / simple_service / nacl_simple_rservice.c
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     void                        *thread_factory_data) {
33   NaClLog(4,
34           "NaClSimpleRevClientCtor: this 0x%"NACL_PRIxPTR"\n",
35           (uintptr_t) self);
36   if (!NaClRefCountCtor(&self->base)) {
37     NaClLog(4, "NaClSimpleRevClientCtor: NaClRefCountCtor failed\n");
38     goto done;
39   }
40   if (0 != NaClCommonDescMakeBoundSock(self->bound_and_cap)) {
41     goto bound_failed;
42   }
43
44   self->acceptor = (struct NaClThreadInterface *) NULL;
45   self->client_callback = callback;
46   self->state = state;
47   self->thread_factory_fn = thread_factory_fn;
48   self->thread_factory_data = thread_factory_data;
49   NaClLog(4,
50           ("NaClSimpleRevClientCtor: callback 0x%"NACL_PRIxPTR
51            ", state 0x%"NACL_PRIxPTR"\n"),
52           (uintptr_t) callback,
53           (uintptr_t) state);
54   NACL_VTBL(NaClRefCount, self) =
55       (struct NaClRefCountVtbl *) &kNaClSimpleRevClientVtbl;
56   return 1;
57
58 bound_failed:
59   (*NACL_VTBL(NaClRefCount, self)->Dtor)(&self->base);
60 done:
61   return 0;
62 }
63
64 static void NaClSimpleRevClientDtor(struct NaClRefCount *vself) {
65   struct NaClSimpleRevClient *self =
66       (struct NaClSimpleRevClient *) vself;
67
68   NaClDescUnref(self->bound_and_cap[0]);
69   NaClDescUnref(self->bound_and_cap[1]);
70
71   NACL_VTBL(NaClRefCount, self) = &kNaClRefCountVtbl;
72   (*NACL_VTBL(NaClRefCount, self)->Dtor)(&self->base);
73 }
74
75 struct NaClSimpleRevClientVtbl const kNaClSimpleRevClientVtbl = {
76   {
77     NaClSimpleRevClientDtor,
78   },
79 };
80
81 static void *RevRpcHandlerBase(struct NaClThreadInterface *tif) {
82   struct NaClSimpleRevClient *self =
83       (struct NaClSimpleRevClient *) tif->thread_data;
84
85   int             status;
86   struct NaClDesc *conn;
87
88   NaClLog(4, "Entered RevRpcHandlerBase\n");
89   while (0 == (status =
90                (*NACL_VTBL(NaClDesc, self->bound_and_cap[0])->AcceptConn)(
91                    self->bound_and_cap[0], &conn))) {
92     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     (*self->client_callback)(self->state, tif, conn);
108     NaClLog(4,
109             "RevRpcHandlerBase: callback finished.\n");
110   }
111   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   NaClRefCountUnref((struct NaClRefCount *) self);
123   return (void *) NULL;
124 }
125
126 int NaClSimpleRevClientStartServiceThread(struct NaClSimpleRevClient *self) {
127   NaClLog(4, "Entered NaClSimpleRevClientStartServiceThread\n");
128   if (NULL != self->acceptor) {
129     NaClLog(LOG_FATAL,
130             "NaClSimpleRevClientStartServiceThread: dup - already started\n");
131   }
132   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     NaClLog(4, "NaClSimpleRevClientStartServiceThread: no thread\n");
140     NaClRefCountUnref((struct NaClRefCount *) self);
141     return 0;
142   }
143   return 1;
144 }
145
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) {
152   NaClLog(4,
153           "NaClSimpleRevServiceCtor: this 0x%"NACL_PRIxPTR"\n",
154           (uintptr_t) self);
155   if (!NaClRefCountCtor(&self->base)) {
156     NaClLog(4, "NaClSimpleRevServiceCtor: NaClRefCountCtor failed\n");
157     return 0;
158   }
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;
164
165   NACL_VTBL(NaClRefCount, self) =
166      (struct NaClRefCountVtbl *) &kNaClSimpleRevServiceVtbl;
167
168   NaClLog(4, "Leaving NaClSimpleRevServiceCtor\n");
169   return 1;
170 }
171
172 void NaClSimpleRevServiceDtor(struct NaClRefCount *vself) {
173   struct NaClSimpleRevService *self =
174       (struct NaClSimpleRevService *) vself;
175
176   NaClDescUnref(self->conn_cap);
177   self->conn_cap = NULL;
178   self->handlers = NULL;
179
180   NACL_VTBL(NaClRefCount, self) = &kNaClRefCountVtbl;
181   (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
182 }
183
184 static void *ConnRpcBase(struct NaClThreadInterface *tif) {
185   struct NaClSimpleRevConnection *rev_conn =
186       (struct NaClSimpleRevConnection *) tif->thread_data;
187
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;
194 }
195
196 int NaClSimpleRevServiceConnectAndSpawnHandlerCb(
197     struct NaClSimpleRevService *self,
198     void                        (*exit_cb)(void *instance_data,
199                                            int  server_loop_ret),
200     void                        *instance_data) {
201   int                             status;
202   struct NaClDesc                 *conn = NULL;
203   struct NaClSimpleRevConnection  *rev_conn;
204
205   NaClLog(4, "Entered NaClSimpleRevServiceConnectAndSpawnHandler\n");
206   if (0 != (status =
207             (*NACL_VTBL(NaClDesc, self->conn_cap)->ConnectAddr)(
208                 self->conn_cap, &conn))) {
209     /* failed */
210     NaClLog(3, "NaClSimpleRevServiceConnectAndSpawnHandler: connect failed\n");
211     return status;
212   }
213   if (0 != (status =
214             (*NACL_VTBL(NaClSimpleRevService, self)->RevConnectionFactory)(
215                 self, conn, exit_cb, instance_data, &rev_conn))) {
216     NaClDescUnref(conn);
217     NaClLog(3,
218             ("NaClSimpleRevServiceConnectAndSpawnHandler: factory failed,"
219              " error %d\n"),
220             status);
221     return status;
222   }
223   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   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     NaClLog(3, "NaClSimpleRevServiceConnectAndSpawnHandler: no thread\n");
239     NaClRefCountUnref((struct NaClRefCount *) rev_conn);
240     return -NACL_ABI_EAGAIN;
241   }
242   /* thread owns rev_conn */
243   NaClLog(4, "Leaving NaClSimpleRevServiceConnectAndSpawnHandler\n");
244   return 0;
245 }
246
247 int NaClSimpleRevServiceConnectAndSpawnHandler(
248     struct NaClSimpleRevService *self,
249     void                        *instance_data) {
250   return NaClSimpleRevServiceConnectAndSpawnHandlerCb(
251       self, NULL, instance_data);
252 }
253
254 int NaClSimpleRevServiceConnectionFactory(
255     struct NaClSimpleRevService     *self,
256     struct NaClDesc                 *conn,
257     void                            (*exit_cb)(void *instance_data,
258                                                int  server_loop_ret),
259     void                            *instance_data,
260     struct NaClSimpleRevConnection  **out) {
261   struct NaClSimpleRevConnection *rconn;
262
263   rconn = (struct NaClSimpleRevConnection *) malloc(sizeof *rconn);
264   if (NULL == rconn) {
265     NaClLog(4, "NaClSimpleRevServiceConnectionFactory:"
266             " no memory\n");
267     return -NACL_ABI_EAGAIN;
268   }
269   /*
270    * In the common/degenerate case, factory instance_data becomes
271    * connection instance data.
272    */
273   if (!NaClSimpleRevConnectionCtor(rconn, self, conn,
274                                    exit_cb, instance_data)) {
275     NaClLog(4, "NaClSimpleRevServiceConnectionFactory:"
276             " NaClSimpleRevConnectionCtor failed\n");
277     free(rconn);
278     return -NACL_ABI_EINVAL;
279   }
280
281   *out = rconn;
282   return 0;
283 }
284
285 void NaClSimpleRevServiceRpcHandler(
286     struct NaClSimpleRevService     *self,
287     struct NaClSimpleRevConnection  *conn) {
288   int retval;
289
290   NaClLog(4, "Entered NaClSimpleRevServiceRpcHandler: ServerLoop!\n");
291   retval = NaClSrpcServerLoop(conn->connected_socket,
292                               self->handlers,
293                               conn->instance_data);
294   NaClLog(4,
295           "NaClSimpleRevServiceRpcHandler: NaClSrpcServerLoop returned %d\n",
296           retval);
297   if (NULL != conn->exit_cb) {
298     (*conn->exit_cb)(conn->instance_data, retval);
299   }
300   NaClLog(4, "Leaving NaClSimpleRevServiceRpcHandler\n");
301 }
302
303 struct NaClSimpleRevServiceVtbl const kNaClSimpleRevServiceVtbl = {
304   {
305     NaClSimpleRevServiceDtor,
306   },
307   NaClSimpleRevServiceConnectAndSpawnHandler,
308   NaClSimpleRevServiceConnectAndSpawnHandlerCb,
309   NaClSimpleRevServiceConnectionFactory,
310   NaClSimpleRevServiceRpcHandler,
311 };
312
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) {
320   NaClLog(4,
321           "NaClSimpleRevConnectionCtor: this 0x%"NACL_PRIxPTR"\n",
322           (uintptr_t) self);
323   if (!NaClRefCountCtor(&self->base)) {
324     return 0;
325   }
326
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;
332
333   NACL_VTBL(NaClRefCount, self) =
334       (struct NaClRefCountVtbl *) &kNaClSimpleRevConnectionVtbl;
335   return 1;
336 }
337
338 void NaClSimpleRevConnectionDtor(struct NaClRefCount *vself) {
339   struct NaClSimpleRevConnection *self =
340       (struct NaClSimpleRevConnection *) vself;
341
342   NaClRefCountUnref((struct NaClRefCount *) self->service);
343   NaClRefCountUnref((struct NaClRefCount *) self->connected_socket);
344
345   NACL_VTBL(NaClRefCount, self) = &kNaClRefCountVtbl;
346   (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
347 }
348
349 struct NaClRefCountVtbl kNaClSimpleRevConnectionVtbl = {
350   NaClSimpleRevConnectionDtor,
351 };