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 |