- add sources.
[platform/framework/web/crosswalk.git] / src / ppapi / native_client / tests / nacl_browser / fault_injection / fault_pm_nameservice_test.cc
1 /*
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.
5  */
6
7 /*
8  * Post-message based test for simple rpc based access to name services.
9  *
10  * Converted from srpc_nameservice_test (deprecated), i.e., C -> C++,
11  * srpc -> post message.
12  */
13 #include <string>
14
15 #include <assert.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <inttypes.h>
19 #include <sys/fcntl.h>
20 #include <string.h>
21 #include <unistd.h>
22
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"
27
28 #include "ppapi/cpp/instance.h"
29 #include "ppapi/cpp/module.h"
30 #include "ppapi/cpp/var.h"
31
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"
34
35 #define RNG_OUTPUT_BYTES  1024
36
37 #define BYTES_PER_LINE    32
38 #define BYTE_SPACING      4
39
40 bool            g_ns_channel_initialized = false;
41 NaClSrpcChannel g_ns_channel;
42
43 void dump_output(nacl::StringBuffer *sb, int d, size_t nbytes) {
44   nacl::scoped_array<uint8_t> bytes;
45   size_t                      got;
46   int                         copied;
47
48   bytes.reset(new uint8_t[nbytes]);
49   if (NULL == bytes.get()) {
50     perror("dump_output");
51     fprintf(stderr, "No memory\n");
52     return;
53   }
54   // Read the RNG output.
55   for (got = 0; got < nbytes; got += copied) {
56     copied = read(d, bytes.get() + got, nbytes - got);
57     if (-1 == copied) {
58       perror("dump_output:read");
59       fprintf(stderr, "read failure\n");
60       break;
61     }
62     printf("read(%d, ..., %u) -> %d\n", d, nbytes - got, copied);
63   }
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))) {
70       sb->Printf(" ");
71     }
72     sb->Printf("%02x", bytes[ix]);
73   }
74   sb->Printf("\n");
75 }
76
77 void EnumerateNames(NaClSrpcChannel *nschan, nacl::StringBuffer *sb) {
78   char      buffer[1024];
79   uint32_t  nbytes = sizeof buffer;
80
81   if (NACL_SRPC_RESULT_OK != NaClSrpcInvokeBySignature(nschan,
82                                                        NACL_NAME_SERVICE_LIST,
83                                                        &nbytes, buffer)) {
84     sb->Printf("NaClSrpcInvokeBySignature failed\n");
85     return;
86   }
87   sb->Printf("nbytes = %u\n", (size_t) nbytes);
88   if (nbytes == sizeof buffer) {
89     sb->Printf("Insufficent space for namespace enumeration\n");
90     return;
91   }
92
93   size_t name_len;
94   for (char *p = buffer;
95        static_cast<size_t>(p - buffer) < nbytes;
96        p += name_len) {
97     name_len = strlen(p) + 1;
98     sb->Printf("%s\n", p);
99   }
100 }
101
102 void Initialize(const pp::Var& message_data, nacl::StringBuffer* sb) {
103   if (g_ns_channel_initialized) {
104     return;
105   }
106   int ns = -1;
107   nacl_nameservice(&ns);
108   printf("ns = %d\n", ns);
109   assert(-1 != 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");
114     close(ns);
115   }
116   sb->Printf("NaClSrpcClientCtor succeeded\n");
117   close(ns);
118   g_ns_channel_initialized = 1;
119 }
120
121 //
122 // Return name service output
123 //
124 void NameServiceDump(const pp::Var& message_data, nacl::StringBuffer* sb) {
125   Initialize(message_data, sb);
126   EnumerateNames(&g_ns_channel, sb);
127 }
128
129 //
130 // Dump RNG output into a string.
131 //
132 void RngDump(const pp::Var& message_data, nacl::StringBuffer* sb) {
133   NaClSrpcError rpc_result;
134   int status;
135   int rng;
136
137   Initialize(message_data, sb);
138
139   rpc_result = NaClSrpcInvokeBySignature(&g_ns_channel,
140                                          NACL_NAME_SERVICE_LOOKUP,
141                                          "SecureRandom", O_RDONLY,
142                                          &status, &rng);
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);
147
148   dump_output(sb, rng, RNG_OUTPUT_BYTES);
149   close(rng);
150 }
151
152 void ManifestTest(const pp::Var& message_data, nacl::StringBuffer* sb) {
153   int status = -1;
154   int manifest;
155
156   Initialize(message_data, sb);
157
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);
165     return;
166   }
167   sb->Printf("Got manifest descriptor %d\n", manifest);
168   if (-1 == manifest) {
169     return;
170   }
171
172   // Connect to manifest name server.
173   int manifest_conn = imc_connect(manifest);
174   close(manifest);
175   sb->Printf("got manifest connection %d\n", manifest_conn);
176   if (-1 == manifest_conn) {
177     sb->Printf("could not connect\n");
178     return;
179   }
180   sb->DiscardOutput();
181   sb->Printf("ManifestTest: basic connectivity ok\n");
182
183   close(manifest_conn);
184 }
185
186 struct PostMessageHandlerDesc {
187   char const *request;
188   void (*handler)(const pp::Var& message_data, nacl::StringBuffer* out);
189 };
190
191 // This object represents one time the page says <embed>.
192 class MyInstance : public pp::Instance {
193  public:
194   explicit MyInstance(PP_Instance instance) : pp::Instance(instance) {}
195   virtual ~MyInstance() {}
196   virtual void HandleMessage(const pp::Var& message_data);
197 };
198
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 },
207     { "rng", RngDump },
208     { "manifest_test", ManifestTest },
209     { reinterpret_cast<char const *>(NULL),
210       reinterpret_cast<void (*)(const pp::Var&, nacl::StringBuffer*)>(NULL) }
211   };
212   nacl::StringBuffer sb;
213
214   if (message_data.is_string()) {
215     std::string op_name(message_data.AsString());
216     std::string reply;
217     size_t len;
218
219     fprintf(stderr, "Searching for handler for request \"%s\".\n",
220             op_name.c_str());
221
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);
226         break;
227       }
228     }
229
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 \"");
235     fflush(stderr);
236     write(2, reply.c_str(), len);
237     fprintf(stderr, "\".\n");
238     fflush(stderr);
239
240     PostMessage(pp::Var(sb.ToString()));
241     fprintf(stderr, "returning\n");
242     fflush(stderr);
243   }
244 }
245
246 // This object is the global object representing this plugin library as long
247 // as it is loaded.
248 class MyModule : public pp::Module {
249  public:
250   MyModule() : pp::Module() {}
251   virtual ~MyModule() {}
252
253   // Override CreateInstance to create your customized Instance object.
254   virtual pp::Instance* CreateInstance(PP_Instance instance) {
255     return new MyInstance(instance);
256   }
257 };
258
259 namespace pp {
260
261 // Factory function for your specialization of the Module object.
262 Module* CreateModule() {
263   return new MyModule();
264 }
265
266 }  // namespace pp