| 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/shared/srpc/nacl_srpc.h" |
| 25 #include "native_client/src/untrusted/nacl_ppapi_util/nacl_ppapi_util.h" |
| 26 #include "native_client/src/untrusted/nacl_ppapi_util/string_buffer.h" |
| 27 |
| 28 #include <sys/nacl_syscalls.h> |
| 29 #include <sys/nacl_name_service.h> |
| 30 |
| 31 #include "ppapi/cpp/instance.h" |
| 32 #include "ppapi/cpp/module.h" |
| 33 #include "ppapi/cpp/var.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 |