| Index: src/untrusted/init/simple_service.cc
|
| diff --git a/src/untrusted/init/simple_service.cc b/src/untrusted/init/simple_service.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..042ec8a8c706b103f51487c2caa33c9f513cdbb2
|
| --- /dev/null
|
| +++ b/src/untrusted/init/simple_service.cc
|
| @@ -0,0 +1,130 @@
|
| +// Copyright (c) 2013 The Native Client Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "native_client/src/untrusted/init/simple_service.h"
|
| +
|
| +namespace nacl {
|
| +
|
| +SimpleService::SimpleService(struct NaClSrpcHandlerDesc const *srpc_handlers)
|
| + : handlers_(handlers) {
|
| +}
|
| +
|
| +SimpleService::~SimpleService() {
|
| + close(bound_and_cap_[0]);
|
| + close(bound_and_cap_[1]);
|
| +}
|
| +
|
| +SimpleServiceConnection *SimpleService::ConnectionFactoryWithInstanceData(
|
| + int d, void *instance_data) {
|
| + return new SimpleServerConnection(this, d, instance_data);
|
| +}
|
| +
|
| +SimpleServiceConnection *SimpleService::ConnectionFactory(int d) {
|
| + return ConnectionFactoryWithInstanceData(d, this);
|
| +}
|
| +
|
| +SimpleServiceConnection *SimpleService::AcceptConnection() {
|
| + SimpleServiceConnection *connection = NULL;
|
| +
|
| + int d = imc_accept(bound_and_cap_[0]);
|
| + if (d == -1) {
|
| + fprintf(stderr, "imc_accept failed\n");
|
| + goto out;
|
| + }
|
| +
|
| + connetion = ConnectionFactory(d, &connection);
|
| + if (connection == NULL) {
|
| + fprintf(stderr, "ConnectionFactory failed\n");
|
| + goto out_socket;
|
| + }
|
| +
|
| + out_socket:
|
| + close(d);
|
| + out:
|
| + return connection;
|
| +}
|
| +
|
| +int SimpleService::AcceptAndSpawnHandler() {
|
| + SimpleServiceConnection *connection = AcceptConnection(&conn);
|
| + if (connection == NULL) {
|
| + goto abort;
|
| + }
|
| +
|
| + if (!ThreadInterfaceConstructAndStartThread(
|
| + thread_factory_fn_,
|
| + thread_factory_data_,
|
| + RpcHandlerBase,
|
| + conn,
|
| + &conn->thread_)) {
|
| + fprintf(stderr, "no thread\n");
|
| + conn->Unref();
|
| + conn->thread_ = NULL;
|
| + status = -EAGAIN;
|
| + goto abort;
|
| + }
|
| + status = 0;
|
| + abort:
|
| + return status;
|
| +}
|
| +
|
| +static void *AcceptThread(ThreadInterface *tif) {
|
| + SimpleService *server =
|
| + reinterpret_cast<SimpleService *>(tif->thread_data_);
|
| + while (server->AcceptAndSpawnHandler() == 0) {
|
| + continue;
|
| + }
|
| + server->Unref();
|
| + return NULL;
|
| +}
|
| +
|
| +void SimpleService::RpcHandler(SimpleServiceConnection *conn) {
|
| + conn->ServerLoop();
|
| +}
|
| +
|
| +static void *RpcHandlerBase(NaClThreadInterface *tif) {
|
| + SimpleServiceConnection *conn =
|
| + reinterpret_cast<SimpleServiceConnection *>(tif->thread_data_);
|
| +
|
| + conn->server_->RpcHandler(conn);
|
| + conn->Unref();
|
| +
|
| + return NULL;
|
| +}
|
| +
|
| +SimpleServiceConnection::SimpleServiceConnection(SimpleService *server,
|
| + int conn,
|
| + void *instance_data)
|
| + : server_(server->Ref()),
|
| + connected_socket_(conn),
|
| + instance_data_(instance_data) {
|
| +}
|
| +
|
| +SimpleServiceConnection::~SimpleServiceConnection() {
|
| + server_->Unref();
|
| + close(connected_socket_);
|
| +}
|
| +
|
| +int SimpleServiceConnection::ServerLoop() {
|
| + return NaClSrpcServerLoop(connected_socket_,
|
| + server_->handlers_,
|
| + instance_data_);
|
| +}
|
| +
|
| +int SimpleServiceStartServiceThread(const SimpleService &server) {
|
| + server.acceptor = new Thread();
|
| + if (!NaClThreadInterfaceConstructAndStartThread(
|
| + server->thread_factory_fn,
|
| + server->thread_factory_data,
|
| + AcceptThread,
|
| + NaClRefCountRef(&server->base),
|
| + NACL_KERN_STACK_SIZE,
|
| + &server->acceptor)) {
|
| + NaClRefCountUnref(&server->base); /* undo ref in Ctor call arglist */
|
| + server->acceptor = NULL;
|
| + return 0;
|
| + }
|
| + return 1;
|
| +}
|
| +
|
| +} // namespace nacl
|
|
|