OLD | NEW |
| (Empty) |
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 | |
OLD | NEW |