1 : // Copyright (c) 2011 The Native Client Authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 : //
5 :
6 : #include "native_client/src/trusted/sel_universal/reverse_emulate.h"
7 : #include <stdio.h>
8 : #include <map>
9 : #include <set>
10 : #include <string>
11 :
12 : #include "native_client/src/include/portability_io.h"
13 : #include "native_client/src/shared/platform/nacl_check.h"
14 : #include "native_client/src/shared/platform/nacl_log.h"
15 : #include "native_client/src/shared/platform/scoped_ptr_refcount.h"
16 : #include "native_client/src/shared/srpc/nacl_srpc.h"
17 : #include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
18 : #include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h"
19 : #include "native_client/src/trusted/reverse_service/reverse_service.h"
20 : #include "native_client/src/trusted/sel_universal/primitives.h"
21 : #include "native_client/src/trusted/sel_universal/rpc_universal.h"
22 : #include "native_client/src/trusted/sel_universal/srpc_helper.h"
23 :
24 :
25 : // Mock of ReverseInterface for use by nexes.
26 : class ReverseEmulate : public nacl::ReverseInterface {
27 : public:
28 : ReverseEmulate();
29 : virtual ~ReverseEmulate();
30 :
31 : // debugging, messaging
32 : virtual void Log(nacl::string message);
33 :
34 : // Startup handshake
35 : virtual void StartupInitializationComplete();
36 :
37 : // Name service use.
38 : virtual bool EnumerateManifestKeys(std::set<nacl::string>* keys);
39 : virtual bool OpenManifestEntry(nacl::string url_key, int32_t* out_desc);
40 : virtual bool CloseManifestEntry(int32_t desc);
41 : virtual void ReportCrash();
42 :
43 : // The low-order 8 bits of the |exit_status| should be reported to
44 : // any interested parties.
45 : virtual void ReportExitStatus(int exit_status);
46 :
47 : // Send a string as a PostMessage to the browser.
48 : virtual void DoPostMessage(nacl::string message);
49 :
50 : // Request quota for a write to a file.
51 : virtual int64_t RequestQuotaForWrite(nacl::string file_id,
52 : int64_t offset,
53 : int64_t length);
54 :
55 : // covariant impl of Ref()
56 2 : ReverseEmulate* Ref() { // down_cast
57 2 : return reinterpret_cast<ReverseEmulate*>(RefCountBase::Ref());
58 : }
59 :
60 : private:
61 : NACL_DISALLOW_COPY_AND_ASSIGN(ReverseEmulate);
62 : };
63 :
64 : namespace {
65 :
66 : typedef std::map<nacl::string, string> KeyToFileMap;
67 :
68 22 : KeyToFileMap g_key_to_file;
69 :
70 22 : nacl::scoped_ptr_refcount<nacl::ReverseService> g_reverse_service;
71 :
72 : } // end namespace
73 :
74 :
75 : bool ReverseEmulateInit(NaClSrpcChannel* command_channel,
76 2 : nacl::SelLdrLauncher* launcher) {
77 : // Do the SRPC to the command channel to set up the reverse channel.
78 : // This returns a NaClDesc* containing a socket address.
79 2 : NaClLog(1, "ReverseEmulateInit: launching reverse RPC service\n");
80 : NaClDesc* h;
81 : NaClSrpcResultCodes rpc_result =
82 2 : NaClSrpcInvokeBySignature(command_channel, "reverse_setup::h", &h);
83 2 : if (NACL_SRPC_RESULT_OK != rpc_result) {
84 0 : NaClLog(LOG_ERROR, "ReverseEmulateInit: reverse setup failed\n");
85 0 : return false;
86 : }
87 : // Make a nacl::DescWrapper* from the NaClDesc*
88 2 : nacl::scoped_ptr<nacl::DescWrapper> conn_cap(launcher->WrapCleanup(h));
89 2 : if (conn_cap == NULL) {
90 0 : NaClLog(LOG_ERROR, "ReverseEmulateInit: reverse desc wrap failed\n");
91 0 : return false;
92 : }
93 : // The implementation of the ReverseInterface is our emulator class.
94 2 : nacl::scoped_ptr<ReverseEmulate> reverse_interface(new ReverseEmulate());
95 : // Create an instance of ReverseService, which connects to the socket
96 : // address and exports the services from our emulator.
97 : g_reverse_service.reset(new nacl::ReverseService(conn_cap.get(),
98 4 : reverse_interface->Ref()));
99 2 : if (g_reverse_service == NULL) {
100 0 : NaClLog(LOG_ERROR, "ReverseEmulateInit: reverse service ctor failed\n");
101 0 : return false;
102 : }
103 : // Successful creation of ReverseService took ownership of these.
104 2 : reverse_interface.release();
105 2 : conn_cap.release();
106 : // Starts the RPC handler for the reverse interface.
107 2 : if (!g_reverse_service->Start()) {
108 0 : NaClLog(LOG_ERROR, "ReverseEmulateInit: reverse service start failed\n");
109 0 : return false;
110 : }
111 2 : return true;
112 : }
113 :
114 2 : void ReverseEmulateFini() {
115 2 : CHECK(g_reverse_service != NULL);
116 2 : g_reverse_service->WaitForServiceThreadsToExit();
117 2 : g_reverse_service.reset(NULL);
118 2 : }
119 :
120 : bool HandlerReverseEmuAddManifestMapping(NaClCommandLoop* ncl,
121 2 : const std::vector<string>& args) {
122 : UNREFERENCED_PARAMETER(ncl);
123 2 : if (args.size() < 3) {
124 0 : NaClLog(LOG_ERROR, "not enough args\n");
125 0 : return false;
126 : }
127 : NaClLog(1, "HandlerReverseEmulateAddManifestMapping(%s) -> %s\n",
128 2 : args[1].c_str(), args[2].c_str());
129 : // Set the mapping for the key.
130 2 : g_key_to_file[args[1]] = args[2];
131 2 : return true;
132 : }
133 :
134 : bool HandlerReverseEmuDumpManifestMappings(NaClCommandLoop* ncl,
135 0 : const std::vector<string>& args) {
136 : UNREFERENCED_PARAMETER(ncl);
137 0 : if (args.size() != 1) {
138 0 : NaClLog(LOG_ERROR, "unexpected args\n");
139 0 : return false;
140 : }
141 0 : printf("ReverseEmulate manifest mappings:\n");
142 0 : for (KeyToFileMap::iterator i = g_key_to_file.begin();
143 : i != g_key_to_file.end();
144 : ++i) {
145 0 : printf("'%s': '%s'\n", i->first.c_str(), i->second.c_str());
146 : }
147 0 : return true;
148 : }
149 :
150 2 : ReverseEmulate::ReverseEmulate() {
151 2 : NaClLog(1, "ReverseEmulate::ReverseEmulate\n");
152 2 : }
153 :
154 0 : ReverseEmulate::~ReverseEmulate() {
155 0 : NaClLog(1, "ReverseEmulate::~ReverseEmulate\n");
156 0 : }
157 :
158 0 : void ReverseEmulate::Log(nacl::string message) {
159 0 : NaClLog(1, "ReverseEmulate::Log (message=%s)\n", message.c_str());
160 0 : }
161 :
162 2 : void ReverseEmulate::StartupInitializationComplete() {
163 2 : NaClLog(1, "ReverseEmulate::StartupInitializationComplete ()\n");
164 2 : }
165 :
166 2 : bool ReverseEmulate::EnumerateManifestKeys(std::set<nacl::string>* keys) {
167 2 : NaClLog(1, "ReverseEmulate::StartupInitializationComplete ()\n");
168 : // Enumerate the keys.
169 2 : std::set<nacl::string> manifest_keys;
170 4 : for (KeyToFileMap::iterator i = g_key_to_file.begin();
171 : i != g_key_to_file.end();
172 : ++i) {
173 2 : manifest_keys.insert(i->first);
174 : }
175 2 : *keys = manifest_keys;
176 2 : return true;
177 : }
178 :
179 : bool ReverseEmulate::OpenManifestEntry(nacl::string url_key,
180 0 : int32_t* out_desc) {
181 : NaClLog(1, "ReverseEmulate::OpenManifestEntry (url_key=%s)\n",
182 0 : url_key.c_str());
183 0 : *out_desc = -1;
184 : // Find the pathname for the key.
185 0 : if (g_key_to_file.find(url_key) == g_key_to_file.end()) {
186 0 : NaClLog(1, "ReverseEmulate::OpenManifestEntry: no pathname for key.\n");
187 0 : return false;
188 : }
189 0 : nacl::string pathname = g_key_to_file[url_key];
190 : NaClLog(1, "ReverseEmulate::OpenManifestEntry: pathname is %s.\n",
191 0 : pathname.c_str());
192 0 : *out_desc = OPEN(pathname.c_str(), O_RDONLY);
193 0 : return *out_desc >= 0;
194 : }
195 :
196 0 : bool ReverseEmulate::CloseManifestEntry(int32_t desc) {
197 0 : NaClLog(1, "ReverseEmulate::CloseManifestEntry (desc=%d)\n", desc);
198 0 : CLOSE(desc);
199 0 : return true;
200 : }
201 :
202 2 : void ReverseEmulate::ReportCrash() {
203 2 : NaClLog(1, "ReverseEmulate::ReportCrash\n");
204 2 : }
205 :
206 2 : void ReverseEmulate::ReportExitStatus(int exit_status) {
207 : NaClLog(1, "ReverseEmulate::ReportExitStatus (exit_status=%d)\n",
208 2 : exit_status);
209 2 : }
210 :
211 0 : void ReverseEmulate::DoPostMessage(nacl::string message) {
212 0 : NaClLog(1, "ReverseEmulate::DoPostMessage (message=%s)\n", message.c_str());
213 0 : }
214 :
215 : int64_t ReverseEmulate::RequestQuotaForWrite(nacl::string file_id,
216 : int64_t offset,
217 0 : int64_t length) {
218 : NaClLog(1, "ReverseEmulate::RequestQuotaForWrite (file_id=%s, offset=%"
219 : NACL_PRId64", length=%"NACL_PRId64")\n", file_id.c_str(), offset,
220 0 : length);
221 0 : return length;
222 22 : }
|