|
OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (c) 2011 The Native Client 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 * Test for simple rpc based access to name services. | |
9 */ | |
10 | |
11 #include <assert.h> | |
12 #include <stdio.h> | |
13 #include <stdlib.h> | |
14 #include <inttypes.h> | |
15 #include <sys/fcntl.h> | |
16 #include <string.h> | |
17 #include <unistd.h> | |
18 #include <sys/nacl_syscalls.h> | |
19 #if 0 /* swap after SDK update */ | |
20 #include <sys/nacl_name_service.h> | |
21 #else | |
22 #include "native_client/src/trusted/service_runtime/include/sys/nacl_name_servic e.h" | |
23 #endif | |
24 #include <nacl/nacl_srpc.h> | |
25 | |
26 #define RNG_OUTPUT_BYTES 1024 | |
27 | |
28 #define BYTES_PER_LINE 32 | |
29 #define BYTE_SPACING 4 | |
30 | |
31 struct StringBuffer { | |
32 size_t nbytes; | |
33 size_t insert; | |
34 char *buffer; | |
35 }; | |
36 | |
37 NaClSrpcChannel ns_channel; | |
38 | |
39 void StringBufferCtor(struct StringBuffer *sb) { | |
40 sb->nbytes = 1024; | |
41 sb->insert = 0; | |
42 sb->buffer = malloc(sb->nbytes); | |
43 if (NULL == sb->buffer) { | |
44 perror("StringBufferInit::malloc"); | |
45 abort(); | |
46 } | |
47 sb->buffer[0] = '\0'; | |
48 } | |
49 | |
50 void StringBufferDiscardOutput(struct StringBuffer *sb) { | |
51 sb->insert = 0; | |
52 } | |
53 | |
54 void StringBufferDtor(struct StringBuffer *sb) { | |
55 sb->nbytes = 0; | |
56 sb->insert = 0; | |
57 free(sb->buffer); | |
58 sb->buffer = NULL; | |
59 } | |
60 | |
61 void StringBufferPrintf(struct StringBuffer *sb, | |
62 char const *fmt, ...) | |
63 __attribute__((format(printf, 2, 3))); | |
64 | |
65 void StringBufferPrintf(struct StringBuffer *sb, | |
66 char const *fmt, ...) { | |
67 size_t space; | |
68 char *insert_pt; | |
69 va_list ap; | |
70 int written = 0; | |
71 char *new_buffer; | |
72 | |
73 va_start(ap, fmt); | |
74 vfprintf(stderr, fmt, ap); | |
75 va_end(ap); | |
76 | |
77 for (;;) { | |
78 space = sb->nbytes - sb->insert; | |
79 insert_pt = sb->buffer + sb->insert; | |
80 va_start(ap, fmt); | |
81 written = vsnprintf(insert_pt, space, fmt, ap); | |
82 va_end(ap); | |
83 if (written < space) { | |
84 sb->insert += written; | |
85 break; | |
86 } | |
87 /* insufficient space -- grow the buffer */ | |
88 new_buffer = realloc(sb->buffer, 2 * sb->nbytes); | |
89 if (NULL == new_buffer) { | |
90 /* give up */ | |
91 fprintf(stderr, "StringBufferPrintf: no memory\n"); | |
92 break; | |
93 } | |
94 sb->nbytes *= 2; | |
95 sb->buffer = new_buffer; | |
96 } | |
97 } | |
98 | |
99 void dump_output(struct StringBuffer *sb, int d, size_t nbytes) { | |
100 uint8_t *bytes; | |
101 int got; | |
102 int copied; | |
103 int ix; | |
104 | |
105 bytes = malloc(nbytes); | |
106 if (!bytes) { | |
107 perror("dump_output"); | |
108 fprintf(stderr, "No memory\n"); | |
109 return; | |
110 } | |
111 /* read output */ | |
112 for (got = 0; got < nbytes; got += copied) { | |
113 copied = read(d, bytes + got, nbytes - got); | |
114 if (-1 == copied) { | |
115 perror("dump_output:read"); | |
116 fprintf(stderr, "read failure\n"); | |
117 break; | |
118 } | |
119 printf("read(%d, ..., %zd) -> %d\n", d, nbytes - got, copied); | |
120 } | |
121 /* hex dump it */ | |
122 for (ix = 0; ix < got; ++ix) { | |
123 if (0 == (ix & (BYTES_PER_LINE-1))) { | |
124 StringBufferPrintf(sb, "\n%04x:", ix); | |
125 } else if (0 == (ix & (BYTE_SPACING-1))) { | |
126 StringBufferPrintf(sb, " "); | |
127 } | |
128 StringBufferPrintf(sb, "%02x", bytes[ix]); | |
129 } | |
130 StringBufferPrintf(sb, "\n"); | |
131 | |
132 free(bytes); | |
133 } | |
134 | |
135 int EnumerateNames(struct StringBuffer *sb, NaClSrpcChannel *nschan) { | |
136 char buffer[1024]; | |
137 uint32_t nbytes = sizeof buffer; | |
138 char *p; | |
139 size_t name_len; | |
140 | |
141 if (NACL_SRPC_RESULT_OK != NaClSrpcInvokeBySignature(nschan, | |
142 NACL_NAME_SERVICE_LIST, | |
143 &nbytes, buffer)) { | |
144 return 0; | |
145 } | |
146 StringBufferPrintf(sb, "nbytes = %zu\n", (size_t) nbytes); | |
147 if (nbytes == sizeof buffer) { | |
148 fprintf(stderr, "Insufficent space for namespace enumeration\n"); | |
149 return 0; | |
150 } | |
151 for (p = buffer; p - buffer < nbytes; p += name_len) { | |
152 name_len = strlen(p) + 1; | |
153 StringBufferPrintf(sb, "%s\n", p); | |
154 } | |
155 return 1; | |
156 } | |
157 | |
158 /* | |
159 * Return name service output | |
160 */ | |
161 void NameServiceDump(NaClSrpcRpc *rpc, | |
162 NaClSrpcArg **in_args, | |
163 NaClSrpcArg **out_args, | |
164 NaClSrpcClosure *done) { | |
165 struct StringBuffer sb; | |
166 StringBufferCtor(&sb); | |
167 | |
168 if (EnumerateNames(&sb, &ns_channel)) { | |
169 out_args[0]->arrays.str = strdup(sb.buffer); | |
170 rpc->result = NACL_SRPC_RESULT_OK; | |
171 } else { | |
172 rpc->result = NACL_SRPC_RESULT_APP_ERROR; | |
173 } | |
174 done->Run(done); | |
175 StringBufferDtor(&sb); | |
176 } | |
177 | |
178 /* | |
179 * Dump RNG output into a string. | |
180 */ | |
181 void RngDump(NaClSrpcRpc *rpc, | |
182 NaClSrpcArg **in_args, | |
183 NaClSrpcArg **out_args, | |
184 NaClSrpcClosure *done) { | |
185 struct StringBuffer sb; | |
186 int status; | |
187 int rng; | |
188 | |
189 StringBufferCtor(&sb); | |
190 if (NACL_SRPC_RESULT_OK != | |
191 NaClSrpcInvokeBySignature(&ns_channel, NACL_NAME_SERVICE_LOOKUP, | |
192 "SecureRandom", O_RDONLY, &status, &rng)) { | |
193 } | |
noelallen_use_chromium
2011/06/14 22:08:14
Missing an error case? If you are assuming status
bsy
2011/06/15 00:21:03
oops. missing body to the error check. i've chan
| |
194 printf("rpc status %d\n", status); | |
195 assert(NACL_NAME_SERVICE_SUCCESS == status); | |
196 printf("rng descriptor %d\n", rng); | |
197 | |
198 dump_output(&sb, rng, RNG_OUTPUT_BYTES); | |
199 out_args[0]->arrays.str = strdup(sb.buffer); | |
200 rpc->result = NACL_SRPC_RESULT_OK; | |
201 done->Run(done); | |
202 close(rng); | |
203 StringBufferDtor(&sb); | |
204 } | |
205 | |
206 void ManifestTest(NaClSrpcRpc *rpc, | |
207 NaClSrpcArg **in_args, | |
208 NaClSrpcArg **out_args, | |
209 NaClSrpcClosure *done) { | |
210 struct StringBuffer sb; | |
211 int status; | |
212 int manifest; | |
213 char buffer[1024]; | |
214 uint32_t nbytes = sizeof buffer; | |
215 | |
216 /* just get the descriptor for now */ | |
217 StringBufferCtor(&sb); | |
218 if (NACL_SRPC_RESULT_OK != | |
219 NaClSrpcInvokeBySignature(&ns_channel, NACL_NAME_SERVICE_LOOKUP, | |
220 "manifest_proxy", O_RDWR, &status, &manifest)) { | |
221 fprintf(stderr, "nameservice lookup failed, status %d\n", status); | |
222 } | |
223 StringBufferPrintf(&sb, "Got manifest descriptor %d\n", manifest); | |
224 if (-1 != manifest) { | |
225 /* connect to manifest name server */ | |
226 int manifest_conn; | |
227 struct NaClSrpcChannel manifest_channel; | |
228 | |
229 manifest_conn = imc_connect(manifest); | |
230 StringBufferPrintf(&sb, "got manifest connection %d\n", manifest_conn); | |
231 if (-1 == manifest_conn) { | |
232 StringBufferPrintf(&sb, "could not connect\n"); | |
233 goto done; | |
234 } | |
235 close(manifest); | |
236 if (!NaClSrpcClientCtor(&manifest_channel, manifest_conn)) { | |
237 StringBufferPrintf(&sb, "could not build srpc client\n"); | |
238 goto done; | |
239 } | |
240 if (NACL_SRPC_RESULT_OK != | |
241 NaClSrpcInvokeBySignature(&manifest_channel, NACL_NAME_SERVICE_LIST, | |
242 &nbytes, buffer)) { | |
243 StringBufferPrintf(&sb, "manifest list failed\n"); | |
244 goto done; | |
245 } | |
246 StringBufferDiscardOutput(&sb); | |
247 StringBufferPrintf(&sb, "ManifestList: %.*s\n", (int) nbytes, buffer); | |
248 } | |
249 done: | |
250 out_args[0]->arrays.str = strdup(sb.buffer); | |
251 rpc->result = NACL_SRPC_RESULT_OK; | |
252 done->Run(done); | |
253 StringBufferDtor(&sb); | |
254 } | |
255 | |
256 const struct NaClSrpcHandlerDesc srpc_methods[] = { | |
257 /* Export the methods as taking no arguments and returning a string. */ | |
258 { "namedump::s", NameServiceDump }, | |
259 { "rngdump::s", RngDump }, | |
260 { "manifest_test::s", ManifestTest }, | |
261 { NULL, NULL }, | |
262 }; | |
263 | |
264 int main() { | |
265 int ns; | |
266 int connected_socket; | |
267 | |
268 if (!NaClSrpcModuleInit()) { | |
269 return 1; | |
270 } | |
271 /* | |
272 * BEGIN HACK -- test code should move to RPC handlers | |
273 */ | |
274 ns = -1; | |
275 nacl_nameservice(&ns); | |
276 printf("ns = %d\n", ns); | |
277 assert(-1 != ns); | |
278 | |
279 connected_socket = imc_connect(ns); | |
280 assert(-1 != connected_socket); | |
281 if (!NaClSrpcClientCtor(&ns_channel, connected_socket)) { | |
282 fprintf(stderr, "Srpc client channel ctor failed\n"); | |
283 return 1; | |
284 } | |
285 printf("NaClSrpcClientCtor succeeded\n"); | |
286 /* | |
287 * END HACK | |
288 */ | |
289 if (!NaClSrpcAcceptClientConnection(srpc_methods)) { | |
290 return 1; | |
291 } | |
noelallen_use_chromium
2011/06/14 22:08:14
Why not close NS?
bsy
2011/06/15 00:21:03
Done.
| |
292 NaClSrpcModuleFini(); | |
293 return 0; | |
294 } | |
OLD | NEW |