2 * Copyright (c) 2012 The Chromium 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.
8 * Post-message based test for simple rpc based access to name services.
10 * Converted from srpc_nameservice_test (deprecated), i.e., C -> C++,
11 * srpc -> post message.
19 #include <sys/fcntl.h>
23 #include "native_client/src/include/nacl_scoped_ptr.h"
24 #include "native_client/src/public/imc_syscalls.h"
25 #include "native_client/src/public/name_service.h"
26 #include "native_client/src/shared/srpc/nacl_srpc.h"
28 #include "ppapi/cpp/instance.h"
29 #include "ppapi/cpp/module.h"
30 #include "ppapi/cpp/var.h"
32 #include "ppapi/native_client/src/untrusted/nacl_ppapi_util/nacl_ppapi_util.h"
33 #include "ppapi/native_client/src/untrusted/nacl_ppapi_util/string_buffer.h"
35 #define RNG_OUTPUT_BYTES 1024
37 #define BYTES_PER_LINE 32
38 #define BYTE_SPACING 4
40 bool g_ns_channel_initialized
= false;
41 NaClSrpcChannel g_ns_channel
;
43 void dump_output(nacl::StringBuffer
*sb
, int d
, size_t nbytes
) {
44 nacl::scoped_array
<uint8_t> bytes
;
48 bytes
.reset(new uint8_t[nbytes
]);
49 if (NULL
== bytes
.get()) {
50 perror("dump_output");
51 fprintf(stderr
, "No memory\n");
54 // Read the RNG output.
55 for (got
= 0; got
< nbytes
; got
+= copied
) {
56 copied
= read(d
, bytes
.get() + got
, nbytes
- got
);
58 perror("dump_output:read");
59 fprintf(stderr
, "read failure\n");
62 printf("read(%d, ..., %u) -> %d\n", d
, nbytes
- got
, copied
);
64 // Hex dump it so we can eyeball it for randomness. Ideally we
65 // would have a chi-square test here to test randomness.
66 for (size_t ix
= 0; ix
< got
; ++ix
) {
67 if (0 == (ix
& (BYTES_PER_LINE
- 1))) {
68 sb
->Printf("\n%04x:", ix
);
69 } else if (0 == (ix
& (BYTE_SPACING
- 1))) {
72 sb
->Printf("%02x", bytes
[ix
]);
77 void EnumerateNames(NaClSrpcChannel
*nschan
, nacl::StringBuffer
*sb
) {
79 uint32_t nbytes
= sizeof buffer
;
81 if (NACL_SRPC_RESULT_OK
!= NaClSrpcInvokeBySignature(nschan
,
82 NACL_NAME_SERVICE_LIST
,
84 sb
->Printf("NaClSrpcInvokeBySignature failed\n");
87 sb
->Printf("nbytes = %u\n", (size_t) nbytes
);
88 if (nbytes
== sizeof buffer
) {
89 sb
->Printf("Insufficent space for namespace enumeration\n");
94 for (char *p
= buffer
;
95 static_cast<size_t>(p
- buffer
) < nbytes
;
97 name_len
= strlen(p
) + 1;
98 sb
->Printf("%s\n", p
);
102 void Initialize(const pp::Var
& message_data
, nacl::StringBuffer
* sb
) {
103 if (g_ns_channel_initialized
) {
107 nacl_nameservice(&ns
);
108 printf("ns = %d\n", ns
);
110 int connected_socket
= imc_connect(ns
);
111 assert(-1 != connected_socket
);
112 if (!NaClSrpcClientCtor(&g_ns_channel
, connected_socket
)) {
113 sb
->Printf("Srpc client channel ctor failed\n");
116 sb
->Printf("NaClSrpcClientCtor succeeded\n");
118 g_ns_channel_initialized
= 1;
122 // Return name service output
124 void NameServiceDump(const pp::Var
& message_data
, nacl::StringBuffer
* sb
) {
125 Initialize(message_data
, sb
);
126 EnumerateNames(&g_ns_channel
, sb
);
130 // Dump RNG output into a string.
132 void RngDump(const pp::Var
& message_data
, nacl::StringBuffer
* sb
) {
133 NaClSrpcError rpc_result
;
137 Initialize(message_data
, sb
);
139 rpc_result
= NaClSrpcInvokeBySignature(&g_ns_channel
,
140 NACL_NAME_SERVICE_LOOKUP
,
141 "SecureRandom", O_RDONLY
,
143 assert(NACL_SRPC_RESULT_OK
== rpc_result
);
144 printf("rpc status %d\n", status
);
145 assert(NACL_NAME_SERVICE_SUCCESS
== status
);
146 printf("rng descriptor %d\n", rng
);
148 dump_output(sb
, rng
, RNG_OUTPUT_BYTES
);
152 void ManifestTest(const pp::Var
& message_data
, nacl::StringBuffer
* sb
) {
156 Initialize(message_data
, sb
);
158 // Make the name service lookup for the manifest service descriptor.
159 if (NACL_SRPC_RESULT_OK
!=
160 NaClSrpcInvokeBySignature(&g_ns_channel
, NACL_NAME_SERVICE_LOOKUP
,
161 "ManifestNameService", O_RDWR
,
162 &status
, &manifest
) ||
163 NACL_NAME_SERVICE_SUCCESS
!= status
) {
164 fprintf(stderr
, "nameservice lookup failed, status %d\n", status
);
167 sb
->Printf("Got manifest descriptor %d\n", manifest
);
168 if (-1 == manifest
) {
172 // Connect to manifest name server.
173 int manifest_conn
= imc_connect(manifest
);
175 sb
->Printf("got manifest connection %d\n", manifest_conn
);
176 if (-1 == manifest_conn
) {
177 sb
->Printf("could not connect\n");
181 sb
->Printf("ManifestTest: basic connectivity ok\n");
183 close(manifest_conn
);
186 struct PostMessageHandlerDesc
{
188 void (*handler
)(const pp::Var
& message_data
, nacl::StringBuffer
* out
);
191 // This object represents one time the page says <embed>.
192 class MyInstance
: public pp::Instance
{
194 explicit MyInstance(PP_Instance instance
) : pp::Instance(instance
) {}
195 virtual ~MyInstance() {}
196 virtual void HandleMessage(const pp::Var
& message_data
);
199 // HandleMessage gets invoked when postMessage is called on the DOM
200 // element associated with this plugin instance. In this case, if we
201 // are given a string, we'll post a message back to JavaScript with a
202 // reply string -- essentially treating this as a string-based RPC.
203 void MyInstance::HandleMessage(const pp::Var
& message_data
) {
204 static struct PostMessageHandlerDesc kMsgHandlers
[] = {
205 { "init", Initialize
},
206 { "nameservice", NameServiceDump
},
208 { "manifest_test", ManifestTest
},
209 { reinterpret_cast<char const *>(NULL
),
210 reinterpret_cast<void (*)(const pp::Var
&, nacl::StringBuffer
*)>(NULL
) }
212 nacl::StringBuffer sb
;
214 if (message_data
.is_string()) {
215 std::string
op_name(message_data
.AsString());
219 fprintf(stderr
, "Searching for handler for request \"%s\".\n",
222 for (size_t ix
= 0; kMsgHandlers
[ix
].request
!= NULL
; ++ix
) {
223 if (op_name
== kMsgHandlers
[ix
].request
) {
224 fprintf(stderr
, "found at index %u\n", ix
);
225 kMsgHandlers
[ix
].handler(message_data
, &sb
);
230 reply
= sb
.ToString();
231 len
= strlen(reply
.c_str());
232 fprintf(stderr
, "posting reply len %d\n", len
);
233 // fprintf(stderr, "posting reply \"%s\".\n", sb.ToString().c_str());
234 fprintf(stderr
, "posting reply \"");
236 write(2, reply
.c_str(), len
);
237 fprintf(stderr
, "\".\n");
240 PostMessage(pp::Var(sb
.ToString()));
241 fprintf(stderr
, "returning\n");
246 // This object is the global object representing this plugin library as long
248 class MyModule
: public pp::Module
{
250 MyModule() : pp::Module() {}
251 virtual ~MyModule() {}
253 // Override CreateInstance to create your customized Instance object.
254 virtual pp::Instance
* CreateInstance(PP_Instance instance
) {
255 return new MyInstance(instance
);
261 // Factory function for your specialization of the Module object.
262 Module
* CreateModule() {
263 return new MyModule();