2 * Copyright (c) 2012 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/service_runtime/nacl_secure_service.h"
11 #include "native_client/src/public/secure_service.h"
13 #include "native_client/src/shared/platform/nacl_exit.h"
14 #include "native_client/src/shared/platform/nacl_log.h"
15 #include "native_client/src/shared/platform/nacl_sync.h"
16 #include "native_client/src/shared/platform/nacl_sync_checked.h"
17 #include "native_client/src/shared/srpc/nacl_srpc.h"
19 #include "native_client/src/trusted/desc/nacl_desc_invalid.h"
20 #include "native_client/src/trusted/fault_injection/fault_injection.h"
21 #include "native_client/src/trusted/manifest_name_service_proxy/manifest_proxy.h"
22 #include "native_client/src/trusted/simple_service/nacl_simple_service.h"
23 #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
24 #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
25 #include "native_client/src/trusted/service_runtime/nacl_app.h"
26 #include "native_client/src/trusted/service_runtime/nacl_error_code.h"
27 #include "native_client/src/trusted/service_runtime/nacl_reverse_host_interface.h"
28 #include "native_client/src/trusted/service_runtime/nacl_reverse_quota_interface.h"
29 #include "native_client/src/trusted/service_runtime/nacl_signal.h"
30 #include "native_client/src/trusted/service_runtime/sel_ldr.h"
32 struct NaClSrpcHandlerDesc const kNaClSecureServiceHandlers[];
34 int NaClSecureServiceCtor(struct NaClSecureService *self,
36 struct NaClDesc *service_port,
37 struct NaClDesc *sock_addr) {
39 "Entered NaClSecureServiceCtor: self 0x%"NACL_PRIxPTR"\n",
41 if (NACL_FI_ERROR_COND(
42 "NaClSecureServiceCtor__NaClSimpleServiceWithSocketCtor",
43 !NaClSimpleServiceWithSocketCtor(
45 kNaClSecureServiceHandlers,
46 NaClThreadInterfaceThreadFactory,
52 if (!NaClMutexCtor(&self->mu)) {
53 NaClLog(4, "NaClMutexCtor failed\n");
54 goto failure_mutex_ctor;
56 if (!NaClCondVarCtor(&self->cv)) {
57 NaClLog(4, "NaClCondVar failed\n");
58 goto failure_condvar_ctor;
60 NaClXMutexCtor(&self->mu);
61 NaClXCondVarCtor(&self->cv);
63 self->reverse_channel_initialization_state =
64 NACL_REVERSE_CHANNEL_UNINITIALIZED;
65 self->reverse_client = NULL;
67 NACL_VTBL(NaClRefCount, self) =
68 (struct NaClRefCountVtbl *) &kNaClSecureServiceVtbl;
72 NaClMutexDtor(&self->mu);
74 (*NACL_VTBL(NaClRefCount, self)->Dtor)((struct NaClRefCount *) self);
79 void NaClSecureServiceDtor(struct NaClRefCount *vself) {
80 struct NaClSecureService *self = (struct NaClSecureService *) vself;
82 NaClXMutexLock(&self->mu);
83 if (NACL_REVERSE_CHANNEL_UNINITIALIZED !=
84 self->reverse_channel_initialization_state) {
85 while (NACL_REVERSE_CHANNEL_INITIALIZED !=
86 self->reverse_channel_initialization_state) {
87 NaClXCondVarWait(&self->cv, &self->mu);
91 if (0 != self->conn_count) {
93 "SecureService dtor when connection count is nonzero\n");
97 if (NACL_REVERSE_CHANNEL_INITIALIZED ==
98 self->reverse_channel_initialization_state) {
99 NaClSrpcDtor(&self->reverse_channel);
101 if (NULL != self->reverse_client) {
102 NaClRefCountUnref((struct NaClRefCount *) self->reverse_client);
104 NaClXMutexUnlock(&self->mu);
106 NaClCondVarDtor(&self->cv);
107 NaClMutexDtor(&self->mu);
109 NACL_VTBL(NaClRefCount, self) = (struct NaClRefCountVtbl const *)
110 &kNaClSimpleServiceVtbl;
111 (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
114 int NaClSecureServiceConnectionFactory(
115 struct NaClSimpleService *vself,
116 struct NaClDesc *conn,
117 struct NaClSimpleServiceConnection **out) {
118 /* our instance_data is not connection specific */
119 return NaClSimpleServiceConnectionFactoryWithInstanceData(
120 vself, conn, (struct NaClSecureService *) vself, out);
123 static void NaClSecureServiceConnectionCountIncr(
124 struct NaClSecureService *self) {
125 NaClLog(5, "NaClSecureServiceThreadCountIncr\n");
126 NaClXMutexLock(&self->mu);
127 if (0 == ++self->conn_count) {
129 "NaClSecureServiceThreadCountIncr: "
130 "thread count overflow!\n");
132 NaClXMutexUnlock(&self->mu);
135 static void NaClSecureServiceConnectionCountDecr(
136 struct NaClSecureService *self) {
139 NaClLog(5, "NaClSecureServiceThreadCountDecr\n");
140 NaClXMutexLock(&self->mu);
141 if (0 == self->conn_count) {
143 "NaClSecureServiceThreadCountDecr: "
144 "decrementing thread count when count is zero\n");
146 conn_count = --self->conn_count;
147 NaClXMutexUnlock(&self->mu);
149 if (0 == conn_count) {
150 NaClLog(4, "NaClSecureServiceThread: all channels closed, exiting.\n");
152 * Set that we are killed by SIGKILL so that debug stub could report
155 NaClAppShutdown(self->nap, NACL_ABI_W_EXITCODE(0, NACL_ABI_SIGKILL));
159 int NaClSecureServiceAcceptConnection(
160 struct NaClSimpleService *vself,
161 struct NaClSimpleServiceConnection **vconn) {
162 struct NaClSecureService *self =
163 (struct NaClSecureService *) vself;
166 NaClLog(4, "NaClSecureServiceAcceptConnection\n");
167 status = (*kNaClSimpleServiceVtbl.AcceptConnection)(vself, vconn);
169 NaClSecureServiceConnectionCountIncr(self);
171 NaClLog(4, "Leaving NaClSecureServiceAcceptConnection, status %d.\n", status);
175 void NaClSecureServiceRpcHandler(struct NaClSimpleService *vself,
176 struct NaClSimpleServiceConnection *vconn) {
177 struct NaClSecureService *self =
178 (struct NaClSecureService *) vself;
180 NaClLog(4, "NaClSecureChannelThread started\n");
181 (*kNaClSimpleServiceVtbl.RpcHandler)(vself, vconn);
182 NaClLog(4, "NaClSecureChannelThread closed.\n");
183 NaClSecureServiceConnectionCountDecr(self);
186 static void NaClSecureServiceLoadModuleRpcCallback(
188 NaClErrorCode status) {
189 struct NaClSrpcClosure *done_cls =
190 (struct NaClSrpcClosure *) instance_data;
191 UNREFERENCED_PARAMETER(status);
192 NaClLog(4, "NaClSecureChannelLoadModuleRpcCallback: status %d\n", status);
193 (*done_cls->Run)(done_cls);
196 static void NaClSecureServiceLoadModuleRpc(
197 struct NaClSrpcRpc *rpc,
198 struct NaClSrpcArg **in_args,
199 struct NaClSrpcArg **out_args,
200 struct NaClSrpcClosure *done_cls) {
201 struct NaClSecureService *nssp =
202 (struct NaClSecureService *) rpc->channel->server_instance_data;
203 struct NaClDesc *nexe = in_args[0]->u.hval;
204 UNREFERENCED_PARAMETER(out_args);
206 NaClLog(4, "NaClSecureServiceLoadModuleRpc: loading module\n");
207 rpc->result = NACL_SRPC_RESULT_OK;
208 NaClAppLoadModule(nssp->nap,
210 NaClSecureServiceLoadModuleRpcCallback,
215 NaClLog(4, "NaClSecureServiceLoadModuleRpc: done\n");
219 * The first connection is performed by this callback handler. This
220 * spawns a client thread that will bootstrap the other connections by
221 * stashing the connection represented by |conn| to make reverse RPCs
222 * to ask the peer to connect to us. No thread is spawned; we just
223 * wrap access to the connection with a lock.
225 * Subsequent connection callbacks will pass the connection to the
226 * actual thread that made the connection request using |conn|
227 * received in the first connection.
229 static void NaClSecureReverseClientCallback(
231 struct NaClThreadInterface *tif,
232 struct NaClDesc *new_conn) {
233 struct NaClSecureService *self =
234 (struct NaClSecureService *) state;
235 struct NaClApp *nap = self->nap;
236 struct NaClManifestProxy *manifest_proxy;
237 struct NaClReverseHostInterface *reverse_host_interface;
238 struct NaClReverseQuotaInterface *reverse_quota_interface;
239 UNREFERENCED_PARAMETER(tif);
242 ("Entered NaClSecureReverseClientCallback: self 0x%"NACL_PRIxPTR","
243 " nap 0x%"NACL_PRIxPTR", new_conn 0x%"NACL_PRIxPTR"\n"),
244 (uintptr_t) self, (uintptr_t) nap, (uintptr_t) new_conn);
246 NaClXMutexLock(&self->mu);
247 if (NACL_REVERSE_CHANNEL_INITIALIZATING !=
248 self->reverse_channel_initialization_state) {
250 * The reverse channel connection capability is used to make the
251 * RPC that invokes this callback (this callback is invoked on a
252 * reverse channel connect), so the plugin wants to initialize the
253 * reverse channel and in particular the state must be either be
254 * in-progress or finished.
256 NaClLog(LOG_FATAL, "Reverse channel already initialized\n");
258 NaClXMutexUnlock(&self->mu);
259 if (!NaClSrpcClientCtor(&self->reverse_channel, new_conn)) {
260 NaClLog(LOG_FATAL, "Reverse channel SRPC Client Ctor failed\n");
263 reverse_host_interface = (struct NaClReverseHostInterface *)
264 malloc(sizeof *reverse_host_interface);
265 if (NULL == reverse_host_interface ||
267 ("NaClSecureReverseClientCallback"
268 "__NaClReverseInterfaceCtor"),
269 !NaClReverseHostInterfaceCtor(reverse_host_interface,
271 NaClLog(LOG_FATAL, "Reverse interface ctor failed\n");
272 goto cleanup_reverse_host_interface;
274 NaClAppRuntimeHostSetup(nap, (struct NaClRuntimeHostInterface *)
275 reverse_host_interface);
277 reverse_quota_interface = (struct NaClReverseQuotaInterface *)
278 malloc(sizeof *reverse_quota_interface);
279 if (NULL == reverse_quota_interface ||
281 ("NaClSecureReverseClientCallback"
282 "__NaClReverseQuotaInterfaceCtor"),
283 !NaClReverseQuotaInterfaceCtor(reverse_quota_interface,
285 NaClLog(LOG_FATAL, "Reverse quota interface ctor failed\n");
286 goto cleanup_reverse_quota_interface;
288 NaClAppDescQuotaSetup(nap, (struct NaClDescQuotaInterface *)
289 reverse_quota_interface);
291 NaClRefCountSafeUnref((struct NaClRefCount *) reverse_quota_interface);
292 reverse_quota_interface = NULL;
294 manifest_proxy = (struct NaClManifestProxy *)
295 malloc(sizeof *manifest_proxy);
296 if (NULL == manifest_proxy ||
297 !NaClManifestProxyCtor(manifest_proxy,
298 NaClAddrSpSquattingThreadIfFactoryFunction,
301 NaClLog(LOG_FATAL, "Manifest proxy ctor failed\n");
302 goto cleanup_manifest_proxy;
306 * NaClSimpleServiceStartServiceThread requires the nap->mu lock.
308 if (!NaClSimpleServiceStartServiceThread((struct NaClSimpleService *)
310 NaClLog(LOG_FATAL, "ManifestProxy start service failed\n");
311 goto cleanup_manifest_proxy;
314 NaClXMutexLock(&nap->mu);
315 (*NACL_VTBL(NaClNameService, nap->name_service)->
316 CreateDescEntry)(nap->name_service,
317 "ManifestNameService", NACL_ABI_O_RDWR,
318 NaClDescRef(manifest_proxy->base.bound_and_cap[1]));
319 NaClXMutexUnlock(&nap->mu);
321 NaClXMutexLock(&self->mu);
322 self->reverse_channel_initialization_state =
323 NACL_REVERSE_CHANNEL_INITIALIZED;
324 NaClXCondVarBroadcast(&self->cv);
325 NaClXMutexUnlock(&self->mu);
327 cleanup_manifest_proxy:
328 NaClRefCountSafeUnref((struct NaClRefCount *) manifest_proxy);
329 cleanup_reverse_quota_interface:
330 NaClRefCountSafeUnref((struct NaClRefCount *) reverse_quota_interface);
331 cleanup_reverse_host_interface:
332 NaClRefCountSafeUnref((struct NaClRefCount *) reverse_host_interface);
334 NaClLog(4, "Leaving NaClSecureReverseClientCallback\n");
337 static void NaClSecureServiceReverseSetupRpc(
338 struct NaClSrpcRpc *rpc,
339 struct NaClSrpcArg **in_args,
340 struct NaClSrpcArg **out_args,
341 struct NaClSrpcClosure *done_cls) {
342 struct NaClSecureService *nssp =
343 (struct NaClSecureService *) rpc->channel->server_instance_data;
344 struct NaClDesc *rev_addr = NULL;
345 struct NaClSecureReverseClient *rev;
346 UNREFERENCED_PARAMETER(in_args);
348 NaClLog(4, "NaClSecureServiceReverseSetupRpc: reverse setup\n");
350 NaClXMutexLock(&nssp->mu);
351 if (NACL_REVERSE_CHANNEL_UNINITIALIZED !=
352 nssp->reverse_channel_initialization_state) {
353 NaClLog(LOG_ERROR, "NaClSecureServiceReverseSetupRpc:"
354 " reverse channel initialization state not uninitialized\n");
355 rpc->result = NACL_SRPC_RESULT_APP_ERROR;
358 nssp->reverse_channel_initialization_state =
359 NACL_REVERSE_CHANNEL_INITIALIZATING;
360 NaClXCondVarBroadcast(&nssp->cv);
362 /* the reverse connection is still coming */
363 rev = (struct NaClSecureReverseClient *) malloc(sizeof *rev);
365 rpc->result = NACL_SRPC_RESULT_NO_MEMORY;
368 NaClLog(4, "NaClSecureServiceReverseSetupRpc:"
369 " invoking NaClSecureReverseClientCtor\n");
370 if (!NaClSecureReverseClientCtor(rev,
371 NaClSecureReverseClientCallback,
374 rpc->result = NACL_SRPC_RESULT_APP_ERROR;
378 if (!NaClSimpleRevClientStartServiceThread(&rev->base)) {
379 rpc->result = NACL_SRPC_RESULT_APP_ERROR;
383 nssp->reverse_client = (struct NaClSecureReverseClient *) NaClRefCountRef(
384 (struct NaClRefCount *) rev);
386 out_args[0]->u.hval = NaClDescRef(rev->base.bound_and_cap[1]);
387 rpc->result = NACL_SRPC_RESULT_OK;
389 NaClXMutexUnlock(&nssp->mu);
390 NaClLog(4, "NaClSecureServiceReverseSetupRpc: done, "
391 " rev_addr 0x%08"NACL_PRIxPTR"\n",
392 (uintptr_t) rev_addr);
393 (*done_cls->Run)(done_cls);
396 struct StartModuleCallbackState {
398 struct NaClSrpcClosure *cls;
401 static void NaClSecureServiceStartModuleRpcCallback(
403 NaClErrorCode status) {
404 struct StartModuleCallbackState *state =
405 (struct StartModuleCallbackState *) instance_data;
406 NaClLog(4, "NaClSecureChannelStartModuleRpcCallback: status %d\n", status);
409 * The RPC reply is now sent. This has to occur before we signal
410 * the main thread to possibly start, since in the case of a failure
411 * the main thread may quickly exit. If the main thread does this
412 * before we sent the RPC reply, then the plugin will be left
415 *state->out_status = (int) status;
416 (*state->cls->Run)(state->cls);
420 static void NaClSecureServiceStartModuleRpc(
421 struct NaClSrpcRpc *rpc,
422 struct NaClSrpcArg **in_args,
423 struct NaClSrpcArg **out_args,
424 struct NaClSrpcClosure *done_cls) {
425 struct NaClSecureService *nssp =
426 (struct NaClSecureService *) rpc->channel->server_instance_data;
427 struct StartModuleCallbackState *state;
428 UNREFERENCED_PARAMETER(in_args);
430 NaClLog(4, "NaClSecureChannelStartModuleRpc: starting module\n");
433 * When reverse setup is being used, we have to block and wait for reverse
434 * channel to become initialized before we can proceed with start module.
436 NaClXMutexLock(&nssp->mu);
437 if (NACL_REVERSE_CHANNEL_UNINITIALIZED !=
438 nssp->reverse_channel_initialization_state) {
439 while (NACL_REVERSE_CHANNEL_INITIALIZED !=
440 nssp->reverse_channel_initialization_state) {
441 NaClXCondVarWait(&nssp->cv, &nssp->mu);
444 NaClXMutexUnlock(&nssp->mu);
446 state = (struct StartModuleCallbackState *) malloc(sizeof *state);
448 rpc->result = NACL_SRPC_RESULT_NO_MEMORY;
449 (*done_cls->Run)(done_cls);
452 state->out_status = &out_args[0]->u.ival;
453 state->cls = done_cls;
455 rpc->result = NACL_SRPC_RESULT_OK;
456 NaClAppStartModule(nssp->nap,
457 NaClSecureServiceStartModuleRpcCallback,
460 NaClLog(4, "NaClSecureChannelStartModuleRpc: done\n");
463 static void NaClSecureServiceLogRpc(
464 struct NaClSrpcRpc *rpc,
465 struct NaClSrpcArg **in_args,
466 struct NaClSrpcArg **out_args,
467 struct NaClSrpcClosure *done_cls) {
468 int severity = in_args[0]->u.ival;
469 char *msg = in_args[1]->arrays.str;
470 UNREFERENCED_PARAMETER(out_args);
472 NaClLog(5, "NaClSecureChannelLogRpc\n");
473 NaClLog(severity, "%s\n", msg);
474 NaClLog(5, "NaClSecureChannelLogRpc\n");
475 rpc->result = NACL_SRPC_RESULT_OK;
476 (*done_cls->Run)(done_cls);
479 static void NaClSecureServiceShutdownRpc(
480 struct NaClSrpcRpc *rpc,
481 struct NaClSrpcArg **in_args,
482 struct NaClSrpcArg **out_args,
483 struct NaClSrpcClosure *done) {
484 struct NaClSecureService *nssp =
485 (struct NaClSecureService *) rpc->channel->server_instance_data;
486 UNREFERENCED_PARAMETER(rpc);
487 UNREFERENCED_PARAMETER(in_args);
488 UNREFERENCED_PARAMETER(out_args);
489 UNREFERENCED_PARAMETER(done);
491 NaClAppShutdown(nssp->nap, 0);
494 struct NaClSrpcHandlerDesc const kNaClSecureServiceHandlers[] = {
495 { NACL_SECURE_SERVICE_LOAD_MODULE, NaClSecureServiceLoadModuleRpc, },
496 { NACL_SECURE_SERVICE_REVERSE_SETUP, NaClSecureServiceReverseSetupRpc, },
497 { NACL_SECURE_SERVICE_START_MODULE, NaClSecureServiceStartModuleRpc, },
498 { NACL_SECURE_SERVICE_LOG, NaClSecureServiceLogRpc, },
499 { NACL_SECURE_SERVICE_HARD_SHUTDOWN, NaClSecureServiceShutdownRpc, },
500 { (char const *) NULL, (NaClSrpcMethod) NULL, },
503 struct NaClSimpleServiceVtbl const kNaClSecureServiceVtbl = {
505 NaClSecureServiceDtor,
507 NaClSecureServiceConnectionFactory,
508 NaClSecureServiceAcceptConnection,
509 NaClSimpleServiceAcceptAndSpawnHandler,
510 NaClSecureServiceRpcHandler,
513 struct NaClSecureRevClientConnHandler {
514 struct NaClSecureRevClientConnHandler *next;
516 /* used by NaClSimpleRevServiceClient's ClientCallback fn */
519 struct NaClThreadInterface *tif,
520 struct NaClDesc *conn);
524 static void NaClSecureReverseClientInternalCallback(
526 struct NaClThreadInterface *tif,
527 struct NaClDesc *conn) {
528 struct NaClSecureReverseClient *self =
529 (struct NaClSecureReverseClient *) state;
530 struct NaClSecureRevClientConnHandler *hand_ptr;
532 NaClLog(4, "Entered NaClSecureReverseClientInternalCallback\n");
533 hand_ptr = (*NACL_VTBL(NaClSecureReverseClient, self)->RemoveHandler)(self);
534 NaClLog(4, " got callback object %"NACL_PRIxPTR"\n", (uintptr_t) hand_ptr);
536 " callback:0x%"NACL_PRIxPTR"(0x%"NACL_PRIxPTR",0x%"NACL_PRIxPTR")\n",
537 (uintptr_t) hand_ptr->handler,
538 (uintptr_t) hand_ptr->state,
540 (*hand_ptr->handler)(hand_ptr->state, tif, conn);
541 NaClLog(4, "NaClSecureReverseClientInternalCallback: freeing memory\n");
543 NaClLog(4, "Leaving NaClSecureReverseClientInternalCallback\n");
547 * Require an initial connection handler in the Ctor, so that it's
548 * obvious that a reverse client needs to accept an IMC connection
549 * from the server to get things bootstrapped.
551 int NaClSecureReverseClientCtor(
552 struct NaClSecureReverseClient *self,
553 void (*client_callback)(
554 void *, struct NaClThreadInterface*, struct NaClDesc *),
557 "Entered NaClSecureReverseClientCtor, self 0x%"NACL_PRIxPTR"\n",
559 if (!NaClSimpleRevClientCtor(&self->base,
560 NaClSecureReverseClientInternalCallback,
562 NaClThreadInterfaceThreadFactory,
564 goto failure_simple_ctor;
566 NaClLog(4, "NaClSecureReverseClientCtor: Mutex\n");
567 if (!NaClMutexCtor(&self->mu)) {
568 goto failure_mutex_ctor;
570 self->queue_head = (struct NaClSecureRevClientConnHandler *) NULL;
571 self->queue_insert = &self->queue_head;
573 NACL_VTBL(NaClRefCount, self) =
574 (struct NaClRefCountVtbl *) &kNaClSecureReverseClientVtbl;
576 NaClLog(4, "NaClSecureReverseClientCtor: InsertHandler\n");
577 if (!(*NACL_VTBL(NaClSecureReverseClient, self)->
578 InsertHandler)(self, client_callback, state)) {
579 goto failure_handler_insert;
582 NaClLog(4, "Leaving NaClSecureReverseClientCtor\n");
585 failure_handler_insert:
586 NaClLog(4, "NaClSecureReverseClientCtor: InsertHandler failed\n");
587 NACL_VTBL(NaClRefCount, self) =
588 (struct NaClRefCountVtbl *) &kNaClSimpleRevClientVtbl;
590 self->queue_insert = (struct NaClSecureRevClientConnHandler **) NULL;
591 NaClMutexDtor(&self->mu);
594 NaClLog(4, "NaClSecureReverseClientCtor: Mutex failed\n");
595 (*NACL_VTBL(NaClRefCount, self)->Dtor)((struct NaClRefCount *) self);
597 NaClLog(4, "Leaving NaClSecureReverseClientCtor\n");
601 void NaClSecureReverseClientDtor(struct NaClRefCount *vself) {
602 struct NaClSecureReverseClient *self =
603 (struct NaClSecureReverseClient *) vself;
605 struct NaClSecureRevClientConnHandler *entry;
606 struct NaClSecureRevClientConnHandler *next;
608 for (entry = self->queue_head; NULL != entry; entry = next) {
612 NaClMutexDtor(&self->mu);
614 NACL_VTBL(NaClRefCount, self) = (struct NaClRefCountVtbl const *)
615 &kNaClSimpleRevClientVtbl;
616 (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
620 * Caller must set up handler before issuing connection request RPC on
621 * nap->reverse_channel, since otherwise the connection handler queue
622 * may be empty and the connect code would abort. Because the connect
623 * doesn't wait for a handler, we don't need a condvar.
625 * We do not need to serialize on the handlers, since the
626 * RPC-server/IMC-client implementation should not distinguish one
627 * connection from another: it is okay for two handlers to be
628 * inserted, and two connection request RPCs to be preformed
629 * (sequentially, since they are over a single channel), and have the
630 * server side spawn threads that asynchronously connect twice, in the
631 * "incorrect" order, etc.
633 int NaClSecureReverseClientInsertHandler(
634 struct NaClSecureReverseClient *self,
637 struct NaClThreadInterface *thread_if,
638 struct NaClDesc *new_conn),
640 struct NaClSecureRevClientConnHandler *entry;
641 int retval = 0; /* fail */
644 ("NaClSecureReverseClientInsertHandler: "
645 "handler 0x%"NACL_PRIxPTR", state 0x%"NACL_PRIxPTR"\n"),
646 (uintptr_t) handler, (uintptr_t) state);
648 NaClXMutexLock(&self->mu);
650 entry = (struct NaClSecureRevClientConnHandler *) malloc(sizeof *entry);
654 entry->handler = handler;
655 entry->state = state;
656 entry->next = (struct NaClSecureRevClientConnHandler *) NULL;
657 *self->queue_insert = entry;
658 self->queue_insert = &entry->next;
662 NaClXMutexUnlock(&self->mu);
666 struct NaClSecureRevClientConnHandler *NaClSecureReverseClientRemoveHandler(
667 struct NaClSecureReverseClient *self) {
668 struct NaClSecureRevClientConnHandler *head;
670 NaClLog(4, "Entered NaClSecureReverseClientRemoveHandler, acquiring lock\n");
671 NaClXMutexLock(&self->mu);
672 NaClLog(4, "NaClSecureReverseClientRemoveHandler, got lock\n");
673 head = self->queue_head;
676 "NaClSecureReverseClientRemoveHandler: empty handler queue\n");
678 if (NULL == (self->queue_head = head->next)) {
679 NaClLog(4, "NaClSecureReverseClientRemoveHandler, last elt patch up\n");
680 self->queue_insert = &self->queue_head;
682 NaClLog(4, "NaClSecureReverseClientRemoveHandler, unlocking\n");
683 NaClXMutexUnlock(&self->mu);
687 ("Leaving NaClSecureReverseClientRemoveHandler:"
688 " returning %"NACL_PRIxPTR"\n"),
693 struct NaClSecureReverseClientVtbl const kNaClSecureReverseClientVtbl = {
696 NaClSecureReverseClientDtor,
699 NaClSecureReverseClientInsertHandler,
700 NaClSecureReverseClientRemoveHandler,